mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-16 15:11:52 +00:00
Add flex 2.5.37 from flex.sourceforge.net to contrib.
This commit is contained in:
commit
3e102307b7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=250873
42
contrib/flex/COPYING
Normal file
42
contrib/flex/COPYING
Normal file
@ -0,0 +1,42 @@
|
||||
Flex carries the copyright used for BSD software, slightly modified
|
||||
because it originated at the Lawrence Berkeley (not Livermore!) Laboratory,
|
||||
which operates under a contract with the Department of Energy:
|
||||
|
||||
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The Flex Project.
|
||||
|
||||
Copyright (c) 1990, 1997 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
This code is derived from software contributed to Berkeley by
|
||||
Vern Paxson.
|
||||
|
||||
The United States Government has rights in this work pursuant
|
||||
to contract no. DE-AC03-76SF00098 between the United States
|
||||
Department of Energy and the University of California.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
||||
This basically says "do whatever you please with this software except
|
||||
remove this notice or take advantage of the University's (or the flex
|
||||
authors') name".
|
||||
|
||||
Note that the "flex.skl" scanner skeleton carries no copyright notice.
|
||||
You are free to do whatever you please with scanners generated using flex;
|
||||
for them, you are not even bound by the above copyright.
|
7883
contrib/flex/ChangeLog
Normal file
7883
contrib/flex/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
206
contrib/flex/FlexLexer.h
Normal file
206
contrib/flex/FlexLexer.h
Normal file
@ -0,0 +1,206 @@
|
||||
// -*-C++-*-
|
||||
// FlexLexer.h -- define interfaces for lexical analyzer classes generated
|
||||
// by flex
|
||||
|
||||
// Copyright (c) 1993 The Regents of the University of California.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is derived from software contributed to Berkeley by
|
||||
// Kent Williams and Tom Epperly.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
|
||||
// Neither the name of the University nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE.
|
||||
|
||||
// This file defines FlexLexer, an abstract class which specifies the
|
||||
// external interface provided to flex C++ lexer objects, and yyFlexLexer,
|
||||
// which defines a particular lexer class.
|
||||
//
|
||||
// If you want to create multiple lexer classes, you use the -P flag
|
||||
// to rename each yyFlexLexer to some other xxFlexLexer. You then
|
||||
// include <FlexLexer.h> in your other sources once per lexer class:
|
||||
//
|
||||
// #undef yyFlexLexer
|
||||
// #define yyFlexLexer xxFlexLexer
|
||||
// #include <FlexLexer.h>
|
||||
//
|
||||
// #undef yyFlexLexer
|
||||
// #define yyFlexLexer zzFlexLexer
|
||||
// #include <FlexLexer.h>
|
||||
// ...
|
||||
|
||||
#ifndef __FLEX_LEXER_H
|
||||
// Never included before - need to define base class.
|
||||
#define __FLEX_LEXER_H
|
||||
|
||||
#include <iostream>
|
||||
# ifndef FLEX_STD
|
||||
# define FLEX_STD std::
|
||||
# endif
|
||||
|
||||
extern "C++" {
|
||||
|
||||
struct yy_buffer_state;
|
||||
typedef int yy_state_type;
|
||||
|
||||
class FlexLexer {
|
||||
public:
|
||||
virtual ~FlexLexer() { }
|
||||
|
||||
const char* YYText() const { return yytext; }
|
||||
int YYLeng() const { return yyleng; }
|
||||
|
||||
virtual void
|
||||
yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0;
|
||||
virtual struct yy_buffer_state*
|
||||
yy_create_buffer( FLEX_STD istream* s, int size ) = 0;
|
||||
virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0;
|
||||
virtual void yyrestart( FLEX_STD istream* s ) = 0;
|
||||
|
||||
virtual int yylex() = 0;
|
||||
|
||||
// Call yylex with new input/output sources.
|
||||
int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 )
|
||||
{
|
||||
switch_streams( new_in, new_out );
|
||||
return yylex();
|
||||
}
|
||||
|
||||
// Switch to new input/output streams. A nil stream pointer
|
||||
// indicates "keep the current one".
|
||||
virtual void switch_streams( FLEX_STD istream* new_in = 0,
|
||||
FLEX_STD ostream* new_out = 0 ) = 0;
|
||||
|
||||
int lineno() const { return yylineno; }
|
||||
|
||||
int debug() const { return yy_flex_debug; }
|
||||
void set_debug( int flag ) { yy_flex_debug = flag; }
|
||||
|
||||
protected:
|
||||
char* yytext;
|
||||
int yyleng;
|
||||
int yylineno; // only maintained if you use %option yylineno
|
||||
int yy_flex_debug; // only has effect with -d or "%option debug"
|
||||
};
|
||||
|
||||
}
|
||||
#endif // FLEXLEXER_H
|
||||
|
||||
#if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce)
|
||||
// Either this is the first time through (yyFlexLexerOnce not defined),
|
||||
// or this is a repeated include to define a different flavor of
|
||||
// yyFlexLexer, as discussed in the flex manual.
|
||||
#define yyFlexLexerOnce
|
||||
|
||||
extern "C++" {
|
||||
|
||||
class yyFlexLexer : public FlexLexer {
|
||||
public:
|
||||
// arg_yyin and arg_yyout default to the cin and cout, but we
|
||||
// only make that assignment when initializing in yylex().
|
||||
yyFlexLexer( FLEX_STD istream* arg_yyin = 0, FLEX_STD ostream* arg_yyout = 0 );
|
||||
|
||||
virtual ~yyFlexLexer();
|
||||
|
||||
void yy_switch_to_buffer( struct yy_buffer_state* new_buffer );
|
||||
struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size );
|
||||
void yy_delete_buffer( struct yy_buffer_state* b );
|
||||
void yyrestart( FLEX_STD istream* s );
|
||||
|
||||
void yypush_buffer_state( struct yy_buffer_state* new_buffer );
|
||||
void yypop_buffer_state();
|
||||
|
||||
virtual int yylex();
|
||||
virtual void switch_streams( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 );
|
||||
virtual int yywrap();
|
||||
|
||||
protected:
|
||||
virtual int LexerInput( char* buf, int max_size );
|
||||
virtual void LexerOutput( const char* buf, int size );
|
||||
virtual void LexerError( const char* msg );
|
||||
|
||||
void yyunput( int c, char* buf_ptr );
|
||||
int yyinput();
|
||||
|
||||
void yy_load_buffer_state();
|
||||
void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream* s );
|
||||
void yy_flush_buffer( struct yy_buffer_state* b );
|
||||
|
||||
int yy_start_stack_ptr;
|
||||
int yy_start_stack_depth;
|
||||
int* yy_start_stack;
|
||||
|
||||
void yy_push_state( int new_state );
|
||||
void yy_pop_state();
|
||||
int yy_top_state();
|
||||
|
||||
yy_state_type yy_get_previous_state();
|
||||
yy_state_type yy_try_NUL_trans( yy_state_type current_state );
|
||||
int yy_get_next_buffer();
|
||||
|
||||
FLEX_STD istream* yyin; // input source for default LexerInput
|
||||
FLEX_STD ostream* yyout; // output sink for default LexerOutput
|
||||
|
||||
// yy_hold_char holds the character lost when yytext is formed.
|
||||
char yy_hold_char;
|
||||
|
||||
// Number of characters read into yy_ch_buf.
|
||||
int yy_n_chars;
|
||||
|
||||
// Points to current character in buffer.
|
||||
char* yy_c_buf_p;
|
||||
|
||||
int yy_init; // whether we need to initialize
|
||||
int yy_start; // 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 ...
|
||||
int yy_did_buffer_switch_on_eof;
|
||||
|
||||
|
||||
size_t yy_buffer_stack_top; /**< index of top of stack. */
|
||||
size_t yy_buffer_stack_max; /**< capacity of stack. */
|
||||
struct yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */
|
||||
void yyensure_buffer_stack(void);
|
||||
|
||||
// The following are not always needed, but may be depending
|
||||
// on use of certain flex features (like REJECT or yymore()).
|
||||
|
||||
yy_state_type yy_last_accepting_state;
|
||||
char* yy_last_accepting_cpos;
|
||||
|
||||
yy_state_type* yy_state_buf;
|
||||
yy_state_type* yy_state_ptr;
|
||||
|
||||
char* yy_full_match;
|
||||
int* yy_full_state;
|
||||
int yy_full_lp;
|
||||
|
||||
int yy_lp;
|
||||
int yy_looking_for_trail_begin;
|
||||
|
||||
int yy_more_flag;
|
||||
int yy_more_len;
|
||||
int yy_more_offset;
|
||||
int yy_prev_more_offset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // yyFlexLexer || ! yyFlexLexerOnce
|
||||
|
518
contrib/flex/NEWS
Normal file
518
contrib/flex/NEWS
Normal file
@ -0,0 +1,518 @@
|
||||
This is the file NEWS for the flex package. It records user -visible
|
||||
changes between releases of flex.
|
||||
|
||||
See the file COPYING for copying conditions.
|
||||
|
||||
* version 2.5.37 released 2012-08-03
|
||||
|
||||
** Import flex into git. See
|
||||
git://flex.git.sourceforge.net/gitroot/flex/flex.
|
||||
|
||||
** Fix make install target to not fail when the flex++ program is
|
||||
already installed
|
||||
|
||||
** New translations from the translation project: de, fi, pl, vi
|
||||
|
||||
* version 2.5.36 released 2012-07-20
|
||||
|
||||
** various portability fixes that quiet compiler warnings on 64-bit
|
||||
hosts
|
||||
|
||||
** various manual fixes, including correcting the name of a %option and
|
||||
updating some simple examples to use ANSI C syntax
|
||||
|
||||
** various bug fixes that prevent certain error conditions from
|
||||
persisting when they should not persist
|
||||
|
||||
** improvements to the test suite so it behaves better when linking
|
||||
compiled files
|
||||
|
||||
** new translations from the translation project: ca, da, es, fi, fr,
|
||||
ga, ko, pt_br, ro, ru, sv, tr, zh_cn
|
||||
|
||||
** the flex distribution is now built with automake 1.10.1 and automake
|
||||
2.61
|
||||
|
||||
* version 2.5.35 released 2008-02-26
|
||||
|
||||
** fixed bug that prevented flex from accepting certain comments in the
|
||||
scanner file (resolves bugs #1849809 and #1849805)
|
||||
|
||||
** fix bug that prevented headers for all functions from being generated
|
||||
(resolves bug #1628314)
|
||||
|
||||
** change yy_size_t to be size_t (resolves bug #1849812)
|
||||
|
||||
** new de, nl, pl, pt_br, vi translations from the translation project
|
||||
|
||||
* version 2.5.34 released 2007-12-12
|
||||
|
||||
** introduce yylex_init_extra; see the manual for details
|
||||
|
||||
** introduce %option extra-type="your_type *" (resolves bug #1744505)
|
||||
|
||||
** The flex program now parses multiple short concatenated options (resolves bug
|
||||
#1619820). Thanks to Petr Machata of Red Hat on this issue.
|
||||
|
||||
** better checking after yyalloc/yyrealloc (resolves bug #1595967)
|
||||
|
||||
** flex now provides for a libfl_pic.a compiled with position
|
||||
independent code. Particularly useful when including a flex scanner
|
||||
in a shared library and with more recent versions of gcc. Thanks to the Debian project for the idea.
|
||||
|
||||
** SourceForge feature request #1658379: Expose YY_BUF_SIZE in the
|
||||
header file.
|
||||
|
||||
** flex better escapes filenames with special characters in them
|
||||
(resolves bug #1623600)
|
||||
|
||||
** a memory leak was plugged(resolves bug #1601111)
|
||||
|
||||
** pattern language expanded; see the manual for details on the below
|
||||
highlights
|
||||
|
||||
*** pattern options added to specify patterns as case-insensitive or
|
||||
case-sensitive
|
||||
|
||||
*** pattern options to specify whether the "." character should match
|
||||
the newline character
|
||||
|
||||
*** pattern options added to allow ignoring of whitespace in patterns
|
||||
|
||||
*** POSIX character classes may be negated in patterns
|
||||
|
||||
*** patterns may now use set difference, union operators
|
||||
|
||||
** the manual now contains an appendix listing various common patterns
|
||||
which may be useful when writing scanners
|
||||
|
||||
** some memory leaks were removed from the C++ scanner (but the C++
|
||||
scanner is still experimental and may change radically without
|
||||
notice)
|
||||
|
||||
** c++ scanners can now use yywrap
|
||||
|
||||
** added new unit test for c++ and yywrap
|
||||
|
||||
** portability fixes to some unit tests
|
||||
|
||||
** flex man page and flex manual in pdf now distributed in the flex
|
||||
distribution
|
||||
|
||||
** new ca, vi, ga, nl translations from the translation project
|
||||
|
||||
** flex no longer comes with an rpm spec file
|
||||
|
||||
** flex development now happens with automake 1.9.6
|
||||
|
||||
* version 2.5.33 released 2006-2-20
|
||||
|
||||
** all flex resources are now to be found from the website at
|
||||
http://flex.sourceforge.net/
|
||||
|
||||
** there was no release 2.5.32 published
|
||||
|
||||
** numerous bug and security fixes
|
||||
|
||||
** new nl, vi, sv, ro, po, ga, ca, fr, tr translations from the translation project
|
||||
|
||||
** upgrade to use gettext 0.12 (this now makes the "pdf" and "ps"
|
||||
targets in the build system able to be run successfully)
|
||||
|
||||
* version 2.5.31 released 2003-4-1
|
||||
|
||||
** remove --enable-maintainer-mode configure option; none of the
|
||||
Makefiles were using it and it can be unduely confusing
|
||||
|
||||
* version 2.5.30 released 2003-4-1
|
||||
|
||||
** yylineno is per-buffer in reentrant scanners
|
||||
|
||||
** added %top directive for placing code at the top of the generated
|
||||
scanner; see manual for details
|
||||
|
||||
** flex now uses m4 to generate scanners; while this means that
|
||||
scanners are more readable, it means that flex requires m4 to be
|
||||
installed; see manual for details
|
||||
|
||||
* version 2.5.29 released 2003-3-5
|
||||
|
||||
** Automatic stack management for multiple input buffers in C and C++ scanners
|
||||
|
||||
** moved the flex documentation to a new doc/ subdirectory
|
||||
|
||||
** cleanups to the yy namespace
|
||||
|
||||
* version 2.5.28 released 2003-2-12
|
||||
|
||||
** flex is now hosted at sourceforge
|
||||
|
||||
** Fixed trailing slash bug in YY_INPUT macro def
|
||||
|
||||
** Flex now warns if always-interactive is specified with fast or full
|
||||
|
||||
* version 2.5.27 released 2003-1-21
|
||||
|
||||
** flex now works with recent bison versions
|
||||
|
||||
** new pt_br translation from the translation project
|
||||
|
||||
* version 2.5.26 released 2003-1-14
|
||||
|
||||
** Fixed table deserialization bug on big-endian archs. Patch sent from Bryce Nichols <bryce@bnichols.org>
|
||||
|
||||
** yyleng has proper declarations now; this caused flex to generate
|
||||
unusable scanners for some programs
|
||||
|
||||
** the flex distribution now includes a spec file suitable for use
|
||||
with rpm
|
||||
|
||||
** some more c++ fixes
|
||||
|
||||
** new es translation from the translation project
|
||||
|
||||
** slight tweeks to the flex_int*_t types
|
||||
|
||||
** flex now warns about pattern ranges that might be ambiguous when
|
||||
generating a case-insensitive scanner
|
||||
|
||||
|
||||
* version 2.5.25 released 2002-12-2
|
||||
|
||||
** flex now uses flex_int*_t types. For C99 systems, they are just the
|
||||
int*_t types; for non-C99 systems, we just make some typedefs
|
||||
|
||||
** new pt_br translation from the translation project
|
||||
|
||||
* version 2.5.24 released 2002-11-25
|
||||
|
||||
* more portability fixes
|
||||
|
||||
** the manual continues to be updated and edited, but it's still got a
|
||||
ways to go
|
||||
|
||||
** it is possible to have multiple c++ scanners in the same program again
|
||||
|
||||
** new turkish translation from the translation project
|
||||
|
||||
* version 2.5.23 released 2002-10-21
|
||||
|
||||
** more portability fixes
|
||||
|
||||
** the manual includes a title page and a table-of-contents when printed
|
||||
|
||||
** the test suite can be run with "make check" from the top-level
|
||||
directory
|
||||
|
||||
** configure now accepts the --enable-maintainer-mode option
|
||||
|
||||
** gettext functionality is now only available externally
|
||||
|
||||
** the constant FLEX_BETA is defined if flex is a beta release
|
||||
|
||||
** the script create-test was not included in the distribution and it
|
||||
should have been
|
||||
|
||||
* version 2.5.22 released 2002-10-10
|
||||
|
||||
** more portability fixes around how we get ahold of the integral
|
||||
types; there is a constant FLEX_NEED_INTEGRAL_TYPE_DEFINITIONS
|
||||
which you should define if you don't have the <inttypes.h> header
|
||||
file (after you complain to your C vendor for not providing a
|
||||
reasonable C environment)
|
||||
|
||||
** more test suite cleanups; in particular, the test suite should run
|
||||
correctly when build from a different directory
|
||||
|
||||
** upgraded automake to 1.7 and consequently autoconf to 2.54; this
|
||||
means, among other things, that there is some support for
|
||||
formatting the manual in postscript and pdf in the distributed
|
||||
Makefile.in (and therefore in the Makefile built by configure)
|
||||
|
||||
** the flex.1 manpage is generated by help2man; (this has been true
|
||||
for quite a while but was not listed here)
|
||||
|
||||
** flex now includes three defined constants to indicate which version
|
||||
of flex generated a scanner (YY_FLEX_{MAJOR,MINOR,SUBMINOR}_VERSION)
|
||||
|
||||
** flex tries its best to output only the relevant portions of the
|
||||
skeleton when generating a scanner, thus avoiding as much
|
||||
conditional compilation as possible
|
||||
|
||||
* version 2.5.21 released 2002-9-17
|
||||
|
||||
** one of the tests in the test suite broke the dist target
|
||||
|
||||
* version 2.5.20 released 2002-9-16
|
||||
|
||||
** A flex scanner has the ability to save the DFA tables to a file,
|
||||
and load them at runtime when needed; see the manual for details
|
||||
|
||||
** Added %option bison-bridge (--bison-bridge)
|
||||
|
||||
** Removed %option reentrant-bison/--reentrant-bison/-Rb
|
||||
|
||||
** yylineno is present in all scanners; Modified nasty performance
|
||||
penalty warning with yylineno in documentation
|
||||
|
||||
** test-table-opts is now run last in the test suite because it's so fat
|
||||
|
||||
** flex can, to some extent, diagnose where internal problems occur
|
||||
|
||||
** new translations from the translation project: fr, ca, de, ru, sv
|
||||
|
||||
**Flex generates C99 defs now; see YY_TRADITIONAL_FUNC_DEFS in the
|
||||
manual if that's not a good thing for you
|
||||
|
||||
* version 2.5.19 released 2002-9-5
|
||||
|
||||
** prevent segfault on input lines which are longer than the allocated
|
||||
space (problem report from Manoj Srivastava
|
||||
<srivasta@golden-gryphon.com>)
|
||||
|
||||
** Changed option 'header' to 'header-file'
|
||||
|
||||
* version 2.5.18 released 2002-9-4
|
||||
|
||||
** portability fixes for integer constants and in the way the test
|
||||
suite reports its results
|
||||
|
||||
** the test for bison was reporting bison missing when it was, in
|
||||
fact, found
|
||||
|
||||
** if we don't find GNU indent, we're more careful when we're not
|
||||
finding it
|
||||
|
||||
* version 2.5.17 released 2002-8-29
|
||||
|
||||
** more portability fixes
|
||||
|
||||
** updated config.sub and config.guess
|
||||
|
||||
** flex is indented by GNU indent (this was done earlier but not
|
||||
explicitly documented)
|
||||
|
||||
* version 2.5.16 released 2002-8-28
|
||||
|
||||
** c++ scanners compile again
|
||||
|
||||
** there is now an indent target in the top-level Makefile; configure
|
||||
checks for GNU indent which is required for proper operation of the
|
||||
indent target
|
||||
|
||||
** some more portability fixes were made
|
||||
|
||||
** %options and invocation sections of manual merged
|
||||
|
||||
** a c++ test was added to the test suite
|
||||
|
||||
** we're trying to clean up more files in the test suite's make clean
|
||||
targets
|
||||
|
||||
* version 2.5.15 released 2002-8-21
|
||||
|
||||
** reject-state buffer is now dynamically allocated and REJECT buffer
|
||||
variables are reentrant-safe
|
||||
|
||||
** manual now discusses memory usage
|
||||
|
||||
** skeleton now processed by m4 before mkskel.sh; (this only matters
|
||||
if you want to change the skeleton or if you're doing flex development)
|
||||
|
||||
** zh_cn translation added from translation project
|
||||
|
||||
** a bug that caused a segfault has now been fixed
|
||||
|
||||
** the test suite now respects the usual CFLAGS, etc. variables
|
||||
|
||||
** removed some warnings which some tests trigggered with the -s option
|
||||
|
||||
** the flex-generated header file now tries to be smarter about
|
||||
conditionally including start conditions
|
||||
|
||||
** tables code omitted from generated scanner when not used
|
||||
|
||||
* version 2.5.14 released 2002-8-15
|
||||
|
||||
** the tests using the reentrant c scanner as c++ were reworked
|
||||
slightly to be sure that the c++ was enforced
|
||||
|
||||
** de translation now included in the distribution
|
||||
|
||||
** various portability fixes regarding nls support, c++ include
|
||||
headers, etc.
|
||||
|
||||
* version 2.5.13 released 2002-8-15
|
||||
|
||||
** the header file output with %option header is now much smaller
|
||||
|
||||
** Fixed type mismatch in printf in scanner skeleton
|
||||
|
||||
** yylex_init now reports errors
|
||||
|
||||
* version 2.5.12 released 2002-8-8
|
||||
|
||||
** updated gettext support to 0.11.5
|
||||
|
||||
** new fr translation from the translation project
|
||||
|
||||
** bison is no longer needed to build flex; If you are building flex
|
||||
from a release (i.e., not from a cvs snapshot), then you don't need
|
||||
to have a pre-built lex around either (unless you modify scan.l, of
|
||||
course); (This has been true for some time, but was not mentioned
|
||||
here.)
|
||||
|
||||
* version 2.5.11 released 2002-7-31
|
||||
|
||||
** Fixed bug where yyless did not consider yylineno
|
||||
|
||||
** the yylineno performance hit is now gone
|
||||
|
||||
** fixed some typos in the manual and we now include texinfo.tex in
|
||||
the distribution
|
||||
|
||||
** traditional prototypes output for C scanners, controlled by a
|
||||
preprocessor symbol; see documentation for details
|
||||
|
||||
* version 2.5.10 released 2002-7-24
|
||||
|
||||
** yy_globals renamed to yyscanner and yy_globals_t renamed to
|
||||
yy_guts_t
|
||||
|
||||
** added dist-bzip2 option to Makefile.am so we now produce a bzip2'd
|
||||
archive in addition to the standard gzip archive
|
||||
|
||||
* version 2.5.9
|
||||
|
||||
** new tests in test suite: test-mem-{nr,r}, test-posix,
|
||||
test-posixly-correct, test-debug-{nr,r}
|
||||
|
||||
** made changes to work with gcc-3.2 development code
|
||||
|
||||
** ability to choose which memory functions are used in flex
|
||||
|
||||
** new yylex_destroy() function for the non-reentrant scanner
|
||||
|
||||
** new handling of POSIXLY_CORRECT environment variable
|
||||
|
||||
** the test suite now has its copyrights explicitly described
|
||||
|
||||
** new ca, de, fr, ru, sv, tr translations
|
||||
|
||||
* version 2.5.8
|
||||
|
||||
** a new --posix option generates scanners with posix-style abc{1,3}
|
||||
compatible parsing, see manual for the screwy details
|
||||
|
||||
* version 2.5.7
|
||||
|
||||
** configure.in now includes a call to AC_PREREQ to enforce the
|
||||
requirement for autoconf at least 2.50 (This only effects you if
|
||||
you're doing flex development.)
|
||||
|
||||
** configure now uses autoconf's versioning information and configure
|
||||
--help reports the bug-reporting address for flex
|
||||
|
||||
** test suite now only reports success versus failure; reporting
|
||||
skipped is problematic under the current setup
|
||||
|
||||
** compilation with --disable-nls now works
|
||||
|
||||
** flex can now be built in a separate directory
|
||||
|
||||
* version 2.5.6
|
||||
|
||||
** gettext support added (from gettext 0.11)
|
||||
|
||||
*** translations for ca, da, de, es, fr, ko, ru, sv, tr included
|
||||
|
||||
** distribution now built under automake 1.6 and autoconf 2.53
|
||||
|
||||
** command-line option parsing happens differently now:
|
||||
|
||||
*** Added long option parsing
|
||||
|
||||
*** Options -n and -c, previously deprecated, now simply do nothing
|
||||
|
||||
*** Options are now parsed left to right
|
||||
|
||||
** added a number of new options
|
||||
|
||||
*** All positive %options are now accessible from the command line
|
||||
|
||||
*** Added option -D, to define a preprocessor symbol
|
||||
|
||||
*** Added option --header=FILE to specify a C .h file to generate
|
||||
|
||||
*** added option --yywrap to call yywrap on EOF
|
||||
|
||||
*** added option --yylineno to track line count in yylineno
|
||||
|
||||
*** --yyclass=NAME name of C++ class when generating c++ scanners
|
||||
|
||||
*** for long option names which are associated with existing short
|
||||
options, see accompanying documentation
|
||||
|
||||
*** new %option nounistd or command-line --nounistd added to prevent
|
||||
flex from generating #include <unistd.h> on systems that don't
|
||||
have that include file
|
||||
|
||||
** Support for reentrant C scanners has been added
|
||||
|
||||
*** Updated the manual with the new reentrant API
|
||||
|
||||
*** Two new options %option reentrant (-R) and
|
||||
%option reentrant-bison (-Rb)
|
||||
|
||||
*** All globals optionally placed into struct yyglobals_t
|
||||
|
||||
*** All access to globals replaced by macro invocations
|
||||
|
||||
*** All functions optionally take one additional
|
||||
argument, yy_globals
|
||||
|
||||
*** New style for invoking reentrant scanner:
|
||||
yylex_init(void** scanner );
|
||||
yylex( scanner );
|
||||
yylex_destroy( scanner );
|
||||
|
||||
*** Added get/set functions for members of struct yy_globals_t
|
||||
e.g., yyget_text, yyget_leng, etc
|
||||
|
||||
*** Prefix substitution added for new functions
|
||||
|
||||
*** Macro shortcuts to the lengthy get/set functions
|
||||
provided for use in actions, e.g., yytext, yyleng, etc
|
||||
|
||||
*** Arbitrary, user-defined data, "yyextra", may be added to scanner
|
||||
|
||||
** %option nomain no longer implies %option yywrap
|
||||
But the inverse is still true
|
||||
|
||||
** Developer test suite added
|
||||
|
||||
*** TESTS/ directory has been added. Users can
|
||||
'make test' in the TESTS directory to execute the test suite
|
||||
|
||||
** Support for bison variables yylval and yylloc added
|
||||
|
||||
** automake support for the build process
|
||||
|
||||
** manual is now in texinfo/info format
|
||||
|
||||
*** flex.1 removed from distribution
|
||||
|
||||
** flex no longer generates C-language scanners with C++-style
|
||||
comments
|
||||
|
||||
** flex now generates scanners in c++ which are compatible with
|
||||
recent c++ compilers
|
||||
|
||||
** flex input scanner now recognizes '\r' as an EOL character
|
||||
|
||||
See the file ONEWS for changes in earlier releases.
|
||||
|
||||
Local Variables:
|
||||
mode: text
|
||||
mode: outline-minor
|
||||
end:
|
1233
contrib/flex/ONEWS
Normal file
1233
contrib/flex/ONEWS
Normal file
File diff suppressed because it is too large
Load Diff
79
contrib/flex/README
Normal file
79
contrib/flex/README
Normal file
@ -0,0 +1,79 @@
|
||||
This is flex, the fast lexical analyzer generator.
|
||||
|
||||
flex is a tool for generating scanners: programs which recognize
|
||||
lexical patterns in text.
|
||||
|
||||
More information about flex as well as the latest official release of
|
||||
flex can be found at:
|
||||
|
||||
http://flex.sourceforge.net/
|
||||
|
||||
Bug reports should be submitted using the SourceForge Bug Tracker
|
||||
facilities which can be found from flex's SourceForge project page at:
|
||||
|
||||
http://sourceforge.net/projects/flex
|
||||
|
||||
There are several mailing lists available as well:
|
||||
|
||||
flex-announce@lists.sourceforge.net - where posts will be made
|
||||
announcing new releases of flex.
|
||||
|
||||
flex-help@lists.sourceforge.net - where you can post questions about
|
||||
using flex
|
||||
|
||||
flex-devel@lists.sourceforge.net - where you can discuss development of
|
||||
flex itself
|
||||
|
||||
Note that flex is distributed under a copyright very similar to that of
|
||||
BSD Unix, and not under the GNU General Public License (GPL).
|
||||
|
||||
This file is part of flex.
|
||||
|
||||
This code is derived from software contributed to Berkeley by
|
||||
Vern Paxson.
|
||||
|
||||
The United States Government has rights in this work pursuant
|
||||
to contract no. DE-AC03-76SF00098 between the United States
|
||||
Department of Energy and the University of California.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
||||
The flex distribution contains the following files which may be of interest:
|
||||
|
||||
README - This file.
|
||||
|
||||
NEWS - current version number and list of user-visible changes.
|
||||
|
||||
INSTALL - basic installation information.
|
||||
|
||||
ABOUT-NLS - description of internationalization support in flex.
|
||||
|
||||
COPYING - flex's copyright and license.
|
||||
|
||||
doc/ - user documentation.
|
||||
|
||||
examples/ - containing examples of some possible flex scanners and a
|
||||
few other things. See the file examples/README for more details.
|
||||
|
||||
TODO - outstanding bug reports, desired features, etc.
|
||||
|
||||
tests/ - regression tests. See TESTS/README for details.
|
||||
|
||||
po/ - internationalization support files.
|
273
contrib/flex/buf.c
Normal file
273
contrib/flex/buf.c
Normal file
@ -0,0 +1,273 @@
|
||||
/* flex - tool to generate fast lexical analyzers */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
/* Take note: The buffer object is sometimes used as a String buffer (one
|
||||
* continuous string), and sometimes used as a list of strings, usually line by
|
||||
* line.
|
||||
*
|
||||
* The type is specified in buf_init by the elt_size. If the elt_size is
|
||||
* sizeof(char), then the buffer should be treated as string buffer. If the
|
||||
* elt_size is sizeof(char*), then the buffer should be treated as a list of
|
||||
* strings.
|
||||
*
|
||||
* Certain functions are only appropriate for one type or the other.
|
||||
*/
|
||||
|
||||
/* global buffers. */
|
||||
struct Buf userdef_buf; /**< for user #definitions triggered by cmd-line. */
|
||||
struct Buf defs_buf; /**< for #define's autogenerated. List of strings. */
|
||||
struct Buf yydmap_buf; /**< string buffer to hold yydmap elements */
|
||||
struct Buf m4defs_buf; /**< m4 definitions. List of strings. */
|
||||
struct Buf top_buf; /**< contains %top code. String buffer. */
|
||||
|
||||
struct Buf *buf_print_strings(struct Buf * buf, FILE* out)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(!buf || !out)
|
||||
return buf;
|
||||
|
||||
for (i=0; i < buf->nelts; i++){
|
||||
const char * s = ((char**)buf->elts)[i];
|
||||
if(s)
|
||||
fprintf(out, "%s", s);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Append a "%s" formatted string to a string buffer */
|
||||
struct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s)
|
||||
{
|
||||
char *t;
|
||||
size_t tsz;
|
||||
|
||||
t = flex_alloc (tsz = strlen (fmt) + strlen (s) + 1);
|
||||
if (!t)
|
||||
flexfatal (_("Allocation of buffer to print string failed"));
|
||||
snprintf (t, tsz, fmt, s);
|
||||
buf = buf_strappend (buf, t);
|
||||
flex_free (t);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** Append a line directive to the string buffer.
|
||||
* @param buf A string buffer.
|
||||
* @param filename file name
|
||||
* @param lineno line number
|
||||
* @return buf
|
||||
*/
|
||||
struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno)
|
||||
{
|
||||
char *dst, *src, *t;
|
||||
|
||||
t = flex_alloc (strlen ("#line \"\"\n") + /* constant parts */
|
||||
2 * strlen (filename) + /* filename with possibly all backslashes escaped */
|
||||
(int) (1 + log10 (abs (lineno))) + /* line number */
|
||||
1); /* NUL */
|
||||
if (!t)
|
||||
flexfatal (_("Allocation of buffer for line directive failed"));
|
||||
for (dst = t + sprintf (t, "#line %d \"", lineno), src = filename; *src; *dst++ = *src++)
|
||||
if (*src == '\\') /* escape backslashes */
|
||||
*dst++ = '\\';
|
||||
*dst++ = '"';
|
||||
*dst++ = '\n';
|
||||
*dst = '\0';
|
||||
buf = buf_strappend (buf, t);
|
||||
flex_free (t);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/** Append the contents of @a src to @a dest.
|
||||
* @param @a dest the destination buffer
|
||||
* @param @a dest the source buffer
|
||||
* @return @a dest
|
||||
*/
|
||||
struct Buf *buf_concat(struct Buf* dest, const struct Buf* src)
|
||||
{
|
||||
buf_append(dest, src->elts, src->nelts);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/* Appends n characters in str to buf. */
|
||||
struct Buf *buf_strnappend (buf, str, n)
|
||||
struct Buf *buf;
|
||||
const char *str;
|
||||
int n;
|
||||
{
|
||||
buf_append (buf, str, n + 1);
|
||||
|
||||
/* "undo" the '\0' character that buf_append() already copied. */
|
||||
buf->nelts--;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Appends characters in str to buf. */
|
||||
struct Buf *buf_strappend (buf, str)
|
||||
struct Buf *buf;
|
||||
const char *str;
|
||||
{
|
||||
return buf_strnappend (buf, str, strlen (str));
|
||||
}
|
||||
|
||||
/* appends "#define str def\n" */
|
||||
struct Buf *buf_strdefine (buf, str, def)
|
||||
struct Buf *buf;
|
||||
const char *str;
|
||||
const char *def;
|
||||
{
|
||||
buf_strappend (buf, "#define ");
|
||||
buf_strappend (buf, " ");
|
||||
buf_strappend (buf, str);
|
||||
buf_strappend (buf, " ");
|
||||
buf_strappend (buf, def);
|
||||
buf_strappend (buf, "\n");
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer.
|
||||
* @param buf A buffer as a list of strings.
|
||||
* @param def The m4 symbol to define.
|
||||
* @param val The definition; may be NULL.
|
||||
* @return buf
|
||||
*/
|
||||
struct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val)
|
||||
{
|
||||
const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n";
|
||||
char * str;
|
||||
size_t strsz;
|
||||
|
||||
val = val?val:"";
|
||||
str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + strlen(val) + 2);
|
||||
if (!str)
|
||||
flexfatal (_("Allocation of buffer for m4 def failed"));
|
||||
|
||||
snprintf(str, strsz, fmt, def, val);
|
||||
buf_append(buf, &str, 1);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer.
|
||||
* @param buf A buffer as a list of strings.
|
||||
* @param def The m4 symbol to undefine.
|
||||
* @return buf
|
||||
*/
|
||||
struct Buf *buf_m4_undefine (struct Buf *buf, const char* def)
|
||||
{
|
||||
const char * fmt = "m4_undefine( [[%s]])m4_dnl\n";
|
||||
char * str;
|
||||
size_t strsz;
|
||||
|
||||
str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + 2);
|
||||
if (!str)
|
||||
flexfatal (_("Allocation of buffer for m4 undef failed"));
|
||||
|
||||
snprintf(str, strsz, fmt, def);
|
||||
buf_append(buf, &str, 1);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* create buf with 0 elements, each of size elem_size. */
|
||||
void buf_init (buf, elem_size)
|
||||
struct Buf *buf;
|
||||
size_t elem_size;
|
||||
{
|
||||
buf->elts = (void *) 0;
|
||||
buf->nelts = 0;
|
||||
buf->elt_size = elem_size;
|
||||
buf->nmax = 0;
|
||||
}
|
||||
|
||||
/* frees memory */
|
||||
void buf_destroy (buf)
|
||||
struct Buf *buf;
|
||||
{
|
||||
if (buf && buf->elts)
|
||||
flex_free (buf->elts);
|
||||
buf->elts = (void *) 0;
|
||||
}
|
||||
|
||||
|
||||
/* appends ptr[] to buf, grow if necessary.
|
||||
* n_elem is number of elements in ptr[], NOT bytes.
|
||||
* returns buf.
|
||||
* We grow by mod(512) boundaries.
|
||||
*/
|
||||
|
||||
struct Buf *buf_append (buf, ptr, n_elem)
|
||||
struct Buf *buf;
|
||||
const void *ptr;
|
||||
int n_elem;
|
||||
{
|
||||
int n_alloc = 0;
|
||||
|
||||
if (!ptr || n_elem == 0)
|
||||
return buf;
|
||||
|
||||
/* May need to alloc more. */
|
||||
if (n_elem + buf->nelts > buf->nmax) {
|
||||
|
||||
/* exact amount needed... */
|
||||
n_alloc = (n_elem + buf->nelts) * buf->elt_size;
|
||||
|
||||
/* ...plus some extra */
|
||||
if (((n_alloc * buf->elt_size) % 512) != 0
|
||||
&& buf->elt_size < 512)
|
||||
n_alloc +=
|
||||
(512 -
|
||||
((n_alloc * buf->elt_size) % 512)) /
|
||||
buf->elt_size;
|
||||
|
||||
if (!buf->elts)
|
||||
buf->elts =
|
||||
allocate_array (n_alloc, buf->elt_size);
|
||||
else
|
||||
buf->elts =
|
||||
reallocate_array (buf->elts, n_alloc,
|
||||
buf->elt_size);
|
||||
|
||||
buf->nmax = n_alloc;
|
||||
}
|
||||
|
||||
memcpy ((char *) buf->elts + buf->nelts * buf->elt_size, ptr,
|
||||
n_elem * buf->elt_size);
|
||||
buf->nelts += n_elem;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */
|
310
contrib/flex/ccl.c
Normal file
310
contrib/flex/ccl.c
Normal file
@ -0,0 +1,310 @@
|
||||
/* ccl - routines for character classes */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
/* return true if the chr is in the ccl. Takes negation into account. */
|
||||
static bool
|
||||
ccl_contains (const int cclp, const int ch)
|
||||
{
|
||||
int ind, len, i;
|
||||
|
||||
len = ccllen[cclp];
|
||||
ind = cclmap[cclp];
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
if (ccltbl[ind + i] == ch)
|
||||
return !cclng[cclp];
|
||||
|
||||
return cclng[cclp];
|
||||
}
|
||||
|
||||
|
||||
/* ccladd - add a single character to a ccl */
|
||||
|
||||
void ccladd (cclp, ch)
|
||||
int cclp;
|
||||
int ch;
|
||||
{
|
||||
int ind, len, newpos, i;
|
||||
|
||||
check_char (ch);
|
||||
|
||||
len = ccllen[cclp];
|
||||
ind = cclmap[cclp];
|
||||
|
||||
/* check to see if the character is already in the ccl */
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
if (ccltbl[ind + i] == ch)
|
||||
return;
|
||||
|
||||
/* mark newlines */
|
||||
if (ch == nlch)
|
||||
ccl_has_nl[cclp] = true;
|
||||
|
||||
newpos = ind + len;
|
||||
|
||||
if (newpos >= current_max_ccl_tbl_size) {
|
||||
current_max_ccl_tbl_size += MAX_CCL_TBL_SIZE_INCREMENT;
|
||||
|
||||
++num_reallocs;
|
||||
|
||||
ccltbl = reallocate_Character_array (ccltbl,
|
||||
current_max_ccl_tbl_size);
|
||||
}
|
||||
|
||||
ccllen[cclp] = len + 1;
|
||||
ccltbl[newpos] = ch;
|
||||
}
|
||||
|
||||
/* dump_cclp - same thing as list_character_set, but for cclps. */
|
||||
|
||||
static void dump_cclp (FILE* file, int cclp)
|
||||
{
|
||||
register int i;
|
||||
|
||||
putc ('[', file);
|
||||
|
||||
for (i = 0; i < csize; ++i) {
|
||||
if (ccl_contains(cclp, i)){
|
||||
register int start_char = i;
|
||||
|
||||
putc (' ', file);
|
||||
|
||||
fputs (readable_form (i), file);
|
||||
|
||||
while (++i < csize && ccl_contains(cclp,i)) ;
|
||||
|
||||
if (i - 1 > start_char)
|
||||
/* this was a run */
|
||||
fprintf (file, "-%s",
|
||||
readable_form (i - 1));
|
||||
|
||||
putc (' ', file);
|
||||
}
|
||||
}
|
||||
|
||||
putc (']', file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ccl_set_diff - create a new ccl as the set difference of the two given ccls. */
|
||||
int
|
||||
ccl_set_diff (int a, int b)
|
||||
{
|
||||
int d, ch;
|
||||
|
||||
/* create new class */
|
||||
d = cclinit();
|
||||
|
||||
/* In order to handle negation, we spin through all possible chars,
|
||||
* addding each char in a that is not in b.
|
||||
* (This could be O(n^2), but n is small and bounded.)
|
||||
*/
|
||||
for ( ch = 0; ch < csize; ++ch )
|
||||
if (ccl_contains (a, ch) && !ccl_contains(b, ch))
|
||||
ccladd (d, ch);
|
||||
|
||||
/* debug */
|
||||
if (0){
|
||||
fprintf(stderr, "ccl_set_diff (");
|
||||
fprintf(stderr, "\n ");
|
||||
dump_cclp (stderr, a);
|
||||
fprintf(stderr, "\n ");
|
||||
dump_cclp (stderr, b);
|
||||
fprintf(stderr, "\n ");
|
||||
dump_cclp (stderr, d);
|
||||
fprintf(stderr, "\n)\n");
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/* ccl_set_union - create a new ccl as the set union of the two given ccls. */
|
||||
int
|
||||
ccl_set_union (int a, int b)
|
||||
{
|
||||
int d, i;
|
||||
|
||||
/* create new class */
|
||||
d = cclinit();
|
||||
|
||||
/* Add all of a */
|
||||
for (i = 0; i < ccllen[a]; ++i)
|
||||
ccladd (d, ccltbl[cclmap[a] + i]);
|
||||
|
||||
/* Add all of b */
|
||||
for (i = 0; i < ccllen[b]; ++i)
|
||||
ccladd (d, ccltbl[cclmap[b] + i]);
|
||||
|
||||
/* debug */
|
||||
if (0){
|
||||
fprintf(stderr, "ccl_set_union (%d + %d = %d", a, b, d);
|
||||
fprintf(stderr, "\n ");
|
||||
dump_cclp (stderr, a);
|
||||
fprintf(stderr, "\n ");
|
||||
dump_cclp (stderr, b);
|
||||
fprintf(stderr, "\n ");
|
||||
dump_cclp (stderr, d);
|
||||
fprintf(stderr, "\n)\n");
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/* cclinit - return an empty ccl */
|
||||
|
||||
int cclinit ()
|
||||
{
|
||||
if (++lastccl >= current_maxccls) {
|
||||
current_maxccls += MAX_CCLS_INCREMENT;
|
||||
|
||||
++num_reallocs;
|
||||
|
||||
cclmap =
|
||||
reallocate_integer_array (cclmap, current_maxccls);
|
||||
ccllen =
|
||||
reallocate_integer_array (ccllen, current_maxccls);
|
||||
cclng = reallocate_integer_array (cclng, current_maxccls);
|
||||
ccl_has_nl =
|
||||
reallocate_bool_array (ccl_has_nl,
|
||||
current_maxccls);
|
||||
}
|
||||
|
||||
if (lastccl == 1)
|
||||
/* we're making the first ccl */
|
||||
cclmap[lastccl] = 0;
|
||||
|
||||
else
|
||||
/* The new pointer is just past the end of the last ccl.
|
||||
* Since the cclmap points to the \first/ character of a
|
||||
* ccl, adding the length of the ccl to the cclmap pointer
|
||||
* will produce a cursor to the first free space.
|
||||
*/
|
||||
cclmap[lastccl] =
|
||||
cclmap[lastccl - 1] + ccllen[lastccl - 1];
|
||||
|
||||
ccllen[lastccl] = 0;
|
||||
cclng[lastccl] = 0; /* ccl's start out life un-negated */
|
||||
ccl_has_nl[lastccl] = false;
|
||||
|
||||
return lastccl;
|
||||
}
|
||||
|
||||
|
||||
/* cclnegate - negate the given ccl */
|
||||
|
||||
void cclnegate (cclp)
|
||||
int cclp;
|
||||
{
|
||||
cclng[cclp] = 1;
|
||||
ccl_has_nl[cclp] = !ccl_has_nl[cclp];
|
||||
}
|
||||
|
||||
|
||||
/* list_character_set - list the members of a set of characters in CCL form
|
||||
*
|
||||
* Writes to the given file a character-class representation of those
|
||||
* characters present in the given CCL. A character is present if it
|
||||
* has a non-zero value in the cset array.
|
||||
*/
|
||||
|
||||
void list_character_set (file, cset)
|
||||
FILE *file;
|
||||
int cset[];
|
||||
{
|
||||
register int i;
|
||||
|
||||
putc ('[', file);
|
||||
|
||||
for (i = 0; i < csize; ++i) {
|
||||
if (cset[i]) {
|
||||
register int start_char = i;
|
||||
|
||||
putc (' ', file);
|
||||
|
||||
fputs (readable_form (i), file);
|
||||
|
||||
while (++i < csize && cset[i]) ;
|
||||
|
||||
if (i - 1 > start_char)
|
||||
/* this was a run */
|
||||
fprintf (file, "-%s",
|
||||
readable_form (i - 1));
|
||||
|
||||
putc (' ', file);
|
||||
}
|
||||
}
|
||||
|
||||
putc (']', file);
|
||||
}
|
||||
|
||||
/** Determines if the range [c1-c2] is unambiguous in a case-insensitive
|
||||
* scanner. Specifically, if a lowercase or uppercase character, x, is in the
|
||||
* range [c1-c2], then we require that UPPERCASE(x) and LOWERCASE(x) must also
|
||||
* be in the range. If not, then this range is ambiguous, and the function
|
||||
* returns false. For example, [@-_] spans [a-z] but not [A-Z]. Beware that
|
||||
* [a-z] will be labeled ambiguous because it does not include [A-Z].
|
||||
*
|
||||
* @param c1 the lower end of the range
|
||||
* @param c2 the upper end of the range
|
||||
* @return true if [c1-c2] is not ambiguous for a caseless scanner.
|
||||
*/
|
||||
bool range_covers_case (int c1, int c2)
|
||||
{
|
||||
int i, o;
|
||||
|
||||
for (i = c1; i <= c2; i++) {
|
||||
if (has_case (i)) {
|
||||
o = reverse_case (i);
|
||||
if (o < c1 || c2 < o)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Reverse the case of a character, if possible.
|
||||
* @return c if case-reversal does not apply.
|
||||
*/
|
||||
int reverse_case (int c)
|
||||
{
|
||||
return isupper (c) ? tolower (c) : (islower (c) ? toupper (c) : c);
|
||||
}
|
||||
|
||||
/** Return true if c is uppercase or lowercase. */
|
||||
bool has_case (int c)
|
||||
{
|
||||
return (isupper (c) || islower (c)) ? true : false;
|
||||
}
|
1096
contrib/flex/dfa.c
Normal file
1096
contrib/flex/dfa.c
Normal file
File diff suppressed because it is too large
Load Diff
219
contrib/flex/ecs.c
Normal file
219
contrib/flex/ecs.c
Normal file
@ -0,0 +1,219 @@
|
||||
/* ecs - equivalence class routines */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
/* ccl2ecl - convert character classes to set of equivalence classes */
|
||||
|
||||
void ccl2ecl ()
|
||||
{
|
||||
int i, ich, newlen, cclp, ccls, cclmec;
|
||||
|
||||
for (i = 1; i <= lastccl; ++i) {
|
||||
/* We loop through each character class, and for each character
|
||||
* in the class, add the character's equivalence class to the
|
||||
* new "character" class we are creating. Thus when we are all
|
||||
* done, character classes will really consist of collections
|
||||
* of equivalence classes
|
||||
*/
|
||||
|
||||
newlen = 0;
|
||||
cclp = cclmap[i];
|
||||
|
||||
for (ccls = 0; ccls < ccllen[i]; ++ccls) {
|
||||
ich = ccltbl[cclp + ccls];
|
||||
cclmec = ecgroup[ich];
|
||||
|
||||
if (cclmec > 0) {
|
||||
ccltbl[cclp + newlen] = cclmec;
|
||||
++newlen;
|
||||
}
|
||||
}
|
||||
|
||||
ccllen[i] = newlen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* cre8ecs - associate equivalence class numbers with class members
|
||||
*
|
||||
* fwd is the forward linked-list of equivalence class members. bck
|
||||
* is the backward linked-list, and num is the number of class members.
|
||||
*
|
||||
* Returned is the number of classes.
|
||||
*/
|
||||
|
||||
int cre8ecs (fwd, bck, num)
|
||||
int fwd[], bck[], num;
|
||||
{
|
||||
int i, j, numcl;
|
||||
|
||||
numcl = 0;
|
||||
|
||||
/* Create equivalence class numbers. From now on, ABS( bck(x) )
|
||||
* is the equivalence class number for object x. If bck(x)
|
||||
* is positive, then x is the representative of its equivalence
|
||||
* class.
|
||||
*/
|
||||
for (i = 1; i <= num; ++i)
|
||||
if (bck[i] == NIL) {
|
||||
bck[i] = ++numcl;
|
||||
for (j = fwd[i]; j != NIL; j = fwd[j])
|
||||
bck[j] = -numcl;
|
||||
}
|
||||
|
||||
return numcl;
|
||||
}
|
||||
|
||||
|
||||
/* mkeccl - update equivalence classes based on character class xtions
|
||||
*
|
||||
* synopsis
|
||||
* Char ccls[];
|
||||
* int lenccl, fwd[llsiz], bck[llsiz], llsiz, NUL_mapping;
|
||||
* void mkeccl( Char ccls[], int lenccl, int fwd[llsiz], int bck[llsiz],
|
||||
* int llsiz, int NUL_mapping );
|
||||
*
|
||||
* ccls contains the elements of the character class, lenccl is the
|
||||
* number of elements in the ccl, fwd is the forward link-list of equivalent
|
||||
* characters, bck is the backward link-list, and llsiz size of the link-list.
|
||||
*
|
||||
* NUL_mapping is the value which NUL (0) should be mapped to.
|
||||
*/
|
||||
|
||||
void mkeccl (ccls, lenccl, fwd, bck, llsiz, NUL_mapping)
|
||||
Char ccls[];
|
||||
int lenccl, fwd[], bck[], llsiz, NUL_mapping;
|
||||
{
|
||||
int cclp, oldec, newec;
|
||||
int cclm, i, j;
|
||||
static unsigned char cclflags[CSIZE]; /* initialized to all '\0' */
|
||||
|
||||
/* Note that it doesn't matter whether or not the character class is
|
||||
* negated. The same results will be obtained in either case.
|
||||
*/
|
||||
|
||||
cclp = 0;
|
||||
|
||||
while (cclp < lenccl) {
|
||||
cclm = ccls[cclp];
|
||||
|
||||
if (NUL_mapping && cclm == 0)
|
||||
cclm = NUL_mapping;
|
||||
|
||||
oldec = bck[cclm];
|
||||
newec = cclm;
|
||||
|
||||
j = cclp + 1;
|
||||
|
||||
for (i = fwd[cclm]; i != NIL && i <= llsiz; i = fwd[i]) { /* look for the symbol in the character class */
|
||||
for (; j < lenccl; ++j) {
|
||||
register int ccl_char;
|
||||
|
||||
if (NUL_mapping && ccls[j] == 0)
|
||||
ccl_char = NUL_mapping;
|
||||
else
|
||||
ccl_char = ccls[j];
|
||||
|
||||
if (ccl_char > i)
|
||||
break;
|
||||
|
||||
if (ccl_char == i && !cclflags[j]) {
|
||||
/* We found an old companion of cclm
|
||||
* in the ccl. Link it into the new
|
||||
* equivalence class and flag it as
|
||||
* having been processed.
|
||||
*/
|
||||
|
||||
bck[i] = newec;
|
||||
fwd[newec] = i;
|
||||
newec = i;
|
||||
/* Set flag so we don't reprocess. */
|
||||
cclflags[j] = 1;
|
||||
|
||||
/* Get next equivalence class member. */
|
||||
/* continue 2 */
|
||||
goto next_pt;
|
||||
}
|
||||
}
|
||||
|
||||
/* Symbol isn't in character class. Put it in the old
|
||||
* equivalence class.
|
||||
*/
|
||||
|
||||
bck[i] = oldec;
|
||||
|
||||
if (oldec != NIL)
|
||||
fwd[oldec] = i;
|
||||
|
||||
oldec = i;
|
||||
|
||||
next_pt:;
|
||||
}
|
||||
|
||||
if (bck[cclm] != NIL || oldec != bck[cclm]) {
|
||||
bck[cclm] = NIL;
|
||||
fwd[oldec] = NIL;
|
||||
}
|
||||
|
||||
fwd[newec] = NIL;
|
||||
|
||||
/* Find next ccl member to process. */
|
||||
|
||||
for (++cclp; cclflags[cclp] && cclp < lenccl; ++cclp) {
|
||||
/* Reset "doesn't need processing" flag. */
|
||||
cclflags[cclp] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* mkechar - create equivalence class for single character */
|
||||
|
||||
void mkechar (tch, fwd, bck)
|
||||
int tch, fwd[], bck[];
|
||||
{
|
||||
/* If until now the character has been a proper subset of
|
||||
* an equivalence class, break it away to create a new ec
|
||||
*/
|
||||
|
||||
if (fwd[tch] != NIL)
|
||||
bck[fwd[tch]] = bck[tch];
|
||||
|
||||
if (bck[tch] != NIL)
|
||||
fwd[bck[tch]] = fwd[tch];
|
||||
|
||||
fwd[tch] = NIL;
|
||||
bck[tch] = NIL;
|
||||
}
|
444
contrib/flex/filter.c
Normal file
444
contrib/flex/filter.c
Normal file
@ -0,0 +1,444 @@
|
||||
/* filter - postprocessing of flex output through filters */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
static const char * check_4_gnu_m4 =
|
||||
"m4_dnl ifdef(`__gnu__', ,"
|
||||
"`errprint(Flex requires GNU M4. Set the PATH or set the M4 environment variable to its path name.)"
|
||||
" m4exit(2)')\n";
|
||||
|
||||
|
||||
/** global chain. */
|
||||
struct filter *output_chain = NULL;
|
||||
|
||||
/* Allocate and initialize an external filter.
|
||||
* @param chain the current chain or NULL for new chain
|
||||
* @param cmd the command to execute.
|
||||
* @param ... a NULL terminated list of (const char*) arguments to command,
|
||||
* not including argv[0].
|
||||
* @return newest filter in chain
|
||||
*/
|
||||
struct filter *filter_create_ext (struct filter *chain, const char *cmd,
|
||||
...)
|
||||
{
|
||||
struct filter *f;
|
||||
int max_args;
|
||||
const char *s;
|
||||
va_list ap;
|
||||
|
||||
/* allocate and initialize new filter */
|
||||
f = (struct filter *) flex_alloc (sizeof (struct filter));
|
||||
if (!f)
|
||||
flexerror (_("flex_alloc failed (f) in filter_create_ext"));
|
||||
memset (f, 0, sizeof (*f));
|
||||
f->filter_func = NULL;
|
||||
f->extra = NULL;
|
||||
f->next = NULL;
|
||||
f->argc = 0;
|
||||
|
||||
if (chain != NULL) {
|
||||
/* append f to end of chain */
|
||||
while (chain->next)
|
||||
chain = chain->next;
|
||||
chain->next = f;
|
||||
}
|
||||
|
||||
|
||||
/* allocate argv, and populate it with the argument list. */
|
||||
max_args = 8;
|
||||
f->argv =
|
||||
(const char **) flex_alloc (sizeof (char *) *
|
||||
(max_args + 1));
|
||||
if (!f->argv)
|
||||
flexerror (_("flex_alloc failed (f->argv) in filter_create_ext"));
|
||||
f->argv[f->argc++] = cmd;
|
||||
|
||||
va_start (ap, cmd);
|
||||
while ((s = va_arg (ap, const char *)) != NULL) {
|
||||
if (f->argc >= max_args) {
|
||||
max_args += 8;
|
||||
f->argv =
|
||||
(const char **) flex_realloc (f->argv,
|
||||
sizeof (char
|
||||
*) *
|
||||
(max_args +
|
||||
1));
|
||||
}
|
||||
f->argv[f->argc++] = s;
|
||||
}
|
||||
f->argv[f->argc] = NULL;
|
||||
|
||||
va_end (ap);
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Allocate and initialize an internal filter.
|
||||
* @param chain the current chain or NULL for new chain
|
||||
* @param filter_func The function that will perform the filtering.
|
||||
* filter_func should return 0 if successful, and -1
|
||||
* if an error occurs -- or it can simply exit().
|
||||
* @param extra optional user-defined data to pass to the filter.
|
||||
* @return newest filter in chain
|
||||
*/
|
||||
struct filter *filter_create_int (struct filter *chain,
|
||||
int (*filter_func) (struct filter *),
|
||||
void *extra)
|
||||
{
|
||||
struct filter *f;
|
||||
|
||||
/* allocate and initialize new filter */
|
||||
f = (struct filter *) flex_alloc (sizeof (struct filter));
|
||||
if (!f)
|
||||
flexerror (_("flex_alloc failed in filter_create_int"));
|
||||
memset (f, 0, sizeof (*f));
|
||||
f->next = NULL;
|
||||
f->argc = 0;
|
||||
f->argv = NULL;
|
||||
|
||||
f->filter_func = filter_func;
|
||||
f->extra = extra;
|
||||
|
||||
if (chain != NULL) {
|
||||
/* append f to end of chain */
|
||||
while (chain->next)
|
||||
chain = chain->next;
|
||||
chain->next = f;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/** Fork and exec entire filter chain.
|
||||
* @param chain The head of the chain.
|
||||
* @return true on success.
|
||||
*/
|
||||
bool filter_apply_chain (struct filter * chain)
|
||||
{
|
||||
int pid, pipes[2];
|
||||
int r;
|
||||
const int readsz = 512;
|
||||
char *buf;
|
||||
|
||||
|
||||
/* Tricky recursion, since we want to begin the chain
|
||||
* at the END. Why? Because we need all the forked processes
|
||||
* to be children of the main flex process.
|
||||
*/
|
||||
if (chain)
|
||||
filter_apply_chain (chain->next);
|
||||
else
|
||||
return true;
|
||||
|
||||
/* Now we are the right-most unprocessed link in the chain.
|
||||
*/
|
||||
|
||||
fflush (stdout);
|
||||
fflush (stderr);
|
||||
|
||||
|
||||
if (pipe (pipes) == -1)
|
||||
flexerror (_("pipe failed"));
|
||||
|
||||
if ((pid = fork ()) == -1)
|
||||
flexerror (_("fork failed"));
|
||||
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
|
||||
/* We need stdin (the FILE* stdin) to connect to this new pipe.
|
||||
* There is no portable way to set stdin to a new file descriptor,
|
||||
* as stdin is not an lvalue on some systems (BSD).
|
||||
* So we dup the new pipe onto the stdin descriptor and use a no-op fseek
|
||||
* to sync the stream. This is a Hail Mary situation. It seems to work.
|
||||
*/
|
||||
close (pipes[1]);
|
||||
clearerr(stdin);
|
||||
if (dup2 (pipes[0], fileno (stdin)) == -1)
|
||||
flexfatal (_("dup2(pipes[0],0)"));
|
||||
close (pipes[0]);
|
||||
fseek (stdin, 0, SEEK_CUR);
|
||||
|
||||
/* run as a filter, either internally or by exec */
|
||||
if (chain->filter_func) {
|
||||
int r;
|
||||
|
||||
if ((r = chain->filter_func (chain)) == -1)
|
||||
flexfatal (_("filter_func failed"));
|
||||
exit (0);
|
||||
}
|
||||
else {
|
||||
execvp (chain->argv[0],
|
||||
(char **const) (chain->argv));
|
||||
lerrsf_fatal ( _("exec of %s failed"),
|
||||
chain->argv[0]);
|
||||
}
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Parent */
|
||||
close (pipes[0]);
|
||||
if (dup2 (pipes[1], fileno (stdout)) == -1)
|
||||
flexfatal (_("dup2(pipes[1],1)"));
|
||||
close (pipes[1]);
|
||||
fseek (stdout, 0, SEEK_CUR);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Truncate the chain to max_len number of filters.
|
||||
* @param chain the current chain.
|
||||
* @param max_len the maximum length of the chain.
|
||||
* @return the resulting length of the chain.
|
||||
*/
|
||||
int filter_truncate (struct filter *chain, int max_len)
|
||||
{
|
||||
int len = 1;
|
||||
|
||||
if (!chain)
|
||||
return 0;
|
||||
|
||||
while (chain->next && len < max_len) {
|
||||
chain = chain->next;
|
||||
++len;
|
||||
}
|
||||
|
||||
chain->next = NULL;
|
||||
return len;
|
||||
}
|
||||
|
||||
/** Splits the chain in order to write to a header file.
|
||||
* Similar in spirit to the 'tee' program.
|
||||
* The header file name is in extra.
|
||||
* @return 0 (zero) on success, and -1 on failure.
|
||||
*/
|
||||
int filter_tee_header (struct filter *chain)
|
||||
{
|
||||
/* This function reads from stdin and writes to both the C file and the
|
||||
* header file at the same time.
|
||||
*/
|
||||
|
||||
const int readsz = 512;
|
||||
char *buf;
|
||||
int to_cfd = -1;
|
||||
FILE *to_c = NULL, *to_h = NULL;
|
||||
bool write_header;
|
||||
|
||||
write_header = (chain->extra != NULL);
|
||||
|
||||
/* Store a copy of the stdout pipe, which is already piped to C file
|
||||
* through the running chain. Then create a new pipe to the H file as
|
||||
* stdout, and fork the rest of the chain again.
|
||||
*/
|
||||
|
||||
if ((to_cfd = dup (1)) == -1)
|
||||
flexfatal (_("dup(1) failed"));
|
||||
to_c = fdopen (to_cfd, "w");
|
||||
|
||||
if (write_header) {
|
||||
if (freopen ((char *) chain->extra, "w", stdout) == NULL)
|
||||
flexfatal (_("freopen(headerfilename) failed"));
|
||||
|
||||
filter_apply_chain (chain->next);
|
||||
to_h = stdout;
|
||||
}
|
||||
|
||||
/* Now to_c is a pipe to the C branch, and to_h is a pipe to the H branch.
|
||||
*/
|
||||
|
||||
if (write_header) {
|
||||
fputs (check_4_gnu_m4, to_h);
|
||||
fputs ("m4_changecom`'m4_dnl\n", to_h);
|
||||
fputs ("m4_changequote`'m4_dnl\n", to_h);
|
||||
fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_h);
|
||||
fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_h);
|
||||
fputs ("m4_define( [[M4_YY_IN_HEADER]],[[]])m4_dnl\n",
|
||||
to_h);
|
||||
fprintf (to_h, "#ifndef %sHEADER_H\n", prefix);
|
||||
fprintf (to_h, "#define %sHEADER_H 1\n", prefix);
|
||||
fprintf (to_h, "#define %sIN_HEADER 1\n\n", prefix);
|
||||
fprintf (to_h,
|
||||
"m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n",
|
||||
headerfilename ? headerfilename : "<stdout>");
|
||||
|
||||
}
|
||||
|
||||
fputs (check_4_gnu_m4, to_c);
|
||||
fputs ("m4_changecom`'m4_dnl\n", to_c);
|
||||
fputs ("m4_changequote`'m4_dnl\n", to_c);
|
||||
fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_c);
|
||||
fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_c);
|
||||
fprintf (to_c, "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n",
|
||||
outfilename ? outfilename : "<stdout>");
|
||||
|
||||
buf = (char *) flex_alloc (readsz);
|
||||
if (!buf)
|
||||
flexerror (_("flex_alloc failed in filter_tee_header"));
|
||||
while (fgets (buf, readsz, stdin)) {
|
||||
fputs (buf, to_c);
|
||||
if (write_header)
|
||||
fputs (buf, to_h);
|
||||
}
|
||||
|
||||
if (write_header) {
|
||||
fprintf (to_h, "\n");
|
||||
|
||||
/* write a fake line number. It will get fixed by the linedir filter. */
|
||||
fprintf (to_h, "#line 4000 \"M4_YY_OUTFILE_NAME\"\n");
|
||||
|
||||
fprintf (to_h, "#undef %sIN_HEADER\n", prefix);
|
||||
fprintf (to_h, "#endif /* %sHEADER_H */\n", prefix);
|
||||
fputs ("m4_undefine( [[M4_YY_IN_HEADER]])m4_dnl\n", to_h);
|
||||
|
||||
fflush (to_h);
|
||||
if (ferror (to_h))
|
||||
lerrsf (_("error writing output file %s"),
|
||||
(char *) chain->extra);
|
||||
|
||||
else if (fclose (to_h))
|
||||
lerrsf (_("error closing output file %s"),
|
||||
(char *) chain->extra);
|
||||
}
|
||||
|
||||
fflush (to_c);
|
||||
if (ferror (to_c))
|
||||
lerrsf (_("error writing output file %s"),
|
||||
outfilename ? outfilename : "<stdout>");
|
||||
|
||||
else if (fclose (to_c))
|
||||
lerrsf (_("error closing output file %s"),
|
||||
outfilename ? outfilename : "<stdout>");
|
||||
|
||||
while (wait (0) > 0) ;
|
||||
|
||||
exit (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Adjust the line numbers in the #line directives of the generated scanner.
|
||||
* After the m4 expansion, the line numbers are incorrect since the m4 macros
|
||||
* can add or remove lines. This only adjusts line numbers for generated code,
|
||||
* not user code. This also happens to be a good place to squeeze multiple
|
||||
* blank lines into a single blank line.
|
||||
*/
|
||||
int filter_fix_linedirs (struct filter *chain)
|
||||
{
|
||||
char *buf;
|
||||
const int readsz = 512;
|
||||
int lineno = 1;
|
||||
bool in_gen = true; /* in generated code */
|
||||
bool last_was_blank = false;
|
||||
|
||||
if (!chain)
|
||||
return 0;
|
||||
|
||||
buf = (char *) flex_alloc (readsz);
|
||||
if (!buf)
|
||||
flexerror (_("flex_alloc failed in filter_fix_linedirs"));
|
||||
|
||||
while (fgets (buf, readsz, stdin)) {
|
||||
|
||||
regmatch_t m[10];
|
||||
|
||||
/* Check for #line directive. */
|
||||
if (buf[0] == '#'
|
||||
&& regexec (®ex_linedir, buf, 3, m, 0) == 0) {
|
||||
|
||||
int num;
|
||||
char *fname;
|
||||
|
||||
/* extract the line number and filename */
|
||||
num = regmatch_strtol (&m[1], buf, NULL, 0);
|
||||
fname = regmatch_dup (&m[2], buf);
|
||||
|
||||
if (strcmp (fname,
|
||||
outfilename ? outfilename : "<stdout>")
|
||||
== 0
|
||||
|| strcmp (fname,
|
||||
headerfilename ? headerfilename : "<stdout>")
|
||||
== 0) {
|
||||
|
||||
char *s1, *s2;
|
||||
char filename[MAXLINE];
|
||||
|
||||
s1 = fname;
|
||||
s2 = filename;
|
||||
|
||||
while ((s2 - filename) < (MAXLINE - 1) && *s1) {
|
||||
/* Escape the backslash */
|
||||
if (*s1 == '\\')
|
||||
*s2++ = '\\';
|
||||
/* Escape the double quote */
|
||||
if (*s1 == '\"')
|
||||
*s2++ = '\\';
|
||||
/* Copy the character as usual */
|
||||
*s2++ = *s1++;
|
||||
}
|
||||
|
||||
*s2 = '\0';
|
||||
|
||||
/* Adjust the line directives. */
|
||||
in_gen = true;
|
||||
snprintf (buf, readsz, "#line %d \"%s\"\n",
|
||||
lineno + 1, filename);
|
||||
}
|
||||
else {
|
||||
/* it's a #line directive for code we didn't write */
|
||||
in_gen = false;
|
||||
}
|
||||
|
||||
free (fname);
|
||||
last_was_blank = false;
|
||||
}
|
||||
|
||||
/* squeeze blank lines from generated code */
|
||||
else if (in_gen
|
||||
&& regexec (®ex_blank_line, buf, 0, NULL,
|
||||
0) == 0) {
|
||||
if (last_was_blank)
|
||||
continue;
|
||||
else
|
||||
last_was_blank = true;
|
||||
}
|
||||
|
||||
else {
|
||||
/* it's a line of normal, non-empty code. */
|
||||
last_was_blank = false;
|
||||
}
|
||||
|
||||
fputs (buf, stdout);
|
||||
lineno++;
|
||||
}
|
||||
fflush (stdout);
|
||||
if (ferror (stdout))
|
||||
lerrsf (_("error writing output file %s"),
|
||||
outfilename ? outfilename : "<stdout>");
|
||||
|
||||
else if (fclose (stdout))
|
||||
lerrsf (_("error closing output file %s"),
|
||||
outfilename ? outfilename : "<stdout>");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */
|
3437
contrib/flex/flex.skl
Normal file
3437
contrib/flex/flex.skl
Normal file
File diff suppressed because it is too large
Load Diff
1226
contrib/flex/flexdef.h
Normal file
1226
contrib/flex/flexdef.h
Normal file
File diff suppressed because it is too large
Load Diff
63
contrib/flex/flexint.h
Normal file
63
contrib/flex/flexint.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* flex integer type definitions */
|
||||
|
||||
#ifndef FLEXINT_H
|
||||
#define FLEXINT_H
|
||||
|
||||
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
|
||||
|
||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
|
||||
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
|
||||
* if you want the limit (max/min) macros for int types.
|
||||
*/
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS 1
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
typedef int8_t flex_int8_t;
|
||||
typedef uint8_t flex_uint8_t;
|
||||
typedef int16_t flex_int16_t;
|
||||
typedef uint16_t flex_uint16_t;
|
||||
typedef int32_t flex_int32_t;
|
||||
typedef uint32_t flex_uint32_t;
|
||||
#else
|
||||
typedef signed char flex_int8_t;
|
||||
typedef short int flex_int16_t;
|
||||
typedef int flex_int32_t;
|
||||
typedef unsigned char flex_uint8_t;
|
||||
typedef unsigned short int flex_uint16_t;
|
||||
typedef unsigned int flex_uint32_t;
|
||||
|
||||
/* Limits of integral types. */
|
||||
#ifndef INT8_MIN
|
||||
#define INT8_MIN (-128)
|
||||
#endif
|
||||
#ifndef INT16_MIN
|
||||
#define INT16_MIN (-32767-1)
|
||||
#endif
|
||||
#ifndef INT32_MIN
|
||||
#define INT32_MIN (-2147483647-1)
|
||||
#endif
|
||||
#ifndef INT8_MAX
|
||||
#define INT8_MAX (127)
|
||||
#endif
|
||||
#ifndef INT16_MAX
|
||||
#define INT16_MAX (32767)
|
||||
#endif
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX (2147483647)
|
||||
#endif
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX (255U)
|
||||
#endif
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX (65535U)
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (4294967295U)
|
||||
#endif
|
||||
|
||||
#endif /* ! C99 */
|
||||
|
||||
#endif /* ! FLEXINT_H */
|
2169
contrib/flex/gen.c
Normal file
2169
contrib/flex/gen.c
Normal file
File diff suppressed because it is too large
Load Diff
33
contrib/flex/libmain.c
Normal file
33
contrib/flex/libmain.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* libmain - flex run-time support library "main" function */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
extern int yylex ();
|
||||
|
||||
int main (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
while (yylex () != 0) ;
|
||||
|
||||
return 0;
|
||||
}
|
27
contrib/flex/libyywrap.c
Normal file
27
contrib/flex/libyywrap.c
Normal file
@ -0,0 +1,27 @@
|
||||
/* libyywrap - flex run-time support library "yywrap" function */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
int yywrap (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
1858
contrib/flex/main.c
Normal file
1858
contrib/flex/main.c
Normal file
File diff suppressed because it is too large
Load Diff
1023
contrib/flex/misc.c
Normal file
1023
contrib/flex/misc.c
Normal file
File diff suppressed because it is too large
Load Diff
37
contrib/flex/mkskel.sh
Executable file
37
contrib/flex/mkskel.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#! /bin/sh
|
||||
|
||||
# This file is part of flex.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
|
||||
# Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE.
|
||||
|
||||
cat <<!
|
||||
/* File created from flex.skl via mkskel.sh */
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
const char *skel[] = {
|
||||
!
|
||||
|
||||
sed 's/\\/&&/g' | sed 's/"/\\"/g' | sed 's/.*/ "&",/'
|
||||
|
||||
cat <<!
|
||||
0
|
||||
};
|
||||
!
|
708
contrib/flex/nfa.c
Normal file
708
contrib/flex/nfa.c
Normal file
@ -0,0 +1,708 @@
|
||||
/* nfa - NFA construction routines */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
|
||||
/* declare functions that have forward references */
|
||||
|
||||
int dupmachine PROTO ((int));
|
||||
void mkxtion PROTO ((int, int));
|
||||
|
||||
|
||||
/* add_accept - add an accepting state to a machine
|
||||
*
|
||||
* accepting_number becomes mach's accepting number.
|
||||
*/
|
||||
|
||||
void add_accept (mach, accepting_number)
|
||||
int mach, accepting_number;
|
||||
{
|
||||
/* Hang the accepting number off an epsilon state. if it is associated
|
||||
* with a state that has a non-epsilon out-transition, then the state
|
||||
* will accept BEFORE it makes that transition, i.e., one character
|
||||
* too soon.
|
||||
*/
|
||||
|
||||
if (transchar[finalst[mach]] == SYM_EPSILON)
|
||||
accptnum[finalst[mach]] = accepting_number;
|
||||
|
||||
else {
|
||||
int astate = mkstate (SYM_EPSILON);
|
||||
|
||||
accptnum[astate] = accepting_number;
|
||||
(void) link_machines (mach, astate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* copysingl - make a given number of copies of a singleton machine
|
||||
*
|
||||
* synopsis
|
||||
*
|
||||
* newsng = copysingl( singl, num );
|
||||
*
|
||||
* newsng - a new singleton composed of num copies of singl
|
||||
* singl - a singleton machine
|
||||
* num - the number of copies of singl to be present in newsng
|
||||
*/
|
||||
|
||||
int copysingl (singl, num)
|
||||
int singl, num;
|
||||
{
|
||||
int copy, i;
|
||||
|
||||
copy = mkstate (SYM_EPSILON);
|
||||
|
||||
for (i = 1; i <= num; ++i)
|
||||
copy = link_machines (copy, dupmachine (singl));
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
/* dumpnfa - debugging routine to write out an nfa */
|
||||
|
||||
void dumpnfa (state1)
|
||||
int state1;
|
||||
|
||||
{
|
||||
int sym, tsp1, tsp2, anum, ns;
|
||||
|
||||
fprintf (stderr,
|
||||
_
|
||||
("\n\n********** beginning dump of nfa with start state %d\n"),
|
||||
state1);
|
||||
|
||||
/* We probably should loop starting at firstst[state1] and going to
|
||||
* lastst[state1], but they're not maintained properly when we "or"
|
||||
* all of the rules together. So we use our knowledge that the machine
|
||||
* starts at state 1 and ends at lastnfa.
|
||||
*/
|
||||
|
||||
/* for ( ns = firstst[state1]; ns <= lastst[state1]; ++ns ) */
|
||||
for (ns = 1; ns <= lastnfa; ++ns) {
|
||||
fprintf (stderr, _("state # %4d\t"), ns);
|
||||
|
||||
sym = transchar[ns];
|
||||
tsp1 = trans1[ns];
|
||||
tsp2 = trans2[ns];
|
||||
anum = accptnum[ns];
|
||||
|
||||
fprintf (stderr, "%3d: %4d, %4d", sym, tsp1, tsp2);
|
||||
|
||||
if (anum != NIL)
|
||||
fprintf (stderr, " [%d]", anum);
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
fprintf (stderr, _("********** end of dump\n"));
|
||||
}
|
||||
|
||||
|
||||
/* dupmachine - make a duplicate of a given machine
|
||||
*
|
||||
* synopsis
|
||||
*
|
||||
* copy = dupmachine( mach );
|
||||
*
|
||||
* copy - holds duplicate of mach
|
||||
* mach - machine to be duplicated
|
||||
*
|
||||
* note that the copy of mach is NOT an exact duplicate; rather, all the
|
||||
* transition states values are adjusted so that the copy is self-contained,
|
||||
* as the original should have been.
|
||||
*
|
||||
* also note that the original MUST be contiguous, with its low and high
|
||||
* states accessible by the arrays firstst and lastst
|
||||
*/
|
||||
|
||||
int dupmachine (mach)
|
||||
int mach;
|
||||
{
|
||||
int i, init, state_offset;
|
||||
int state = 0;
|
||||
int last = lastst[mach];
|
||||
|
||||
for (i = firstst[mach]; i <= last; ++i) {
|
||||
state = mkstate (transchar[i]);
|
||||
|
||||
if (trans1[i] != NO_TRANSITION) {
|
||||
mkxtion (finalst[state], trans1[i] + state - i);
|
||||
|
||||
if (transchar[i] == SYM_EPSILON &&
|
||||
trans2[i] != NO_TRANSITION)
|
||||
mkxtion (finalst[state],
|
||||
trans2[i] + state - i);
|
||||
}
|
||||
|
||||
accptnum[state] = accptnum[i];
|
||||
}
|
||||
|
||||
if (state == 0)
|
||||
flexfatal (_("empty machine in dupmachine()"));
|
||||
|
||||
state_offset = state - i + 1;
|
||||
|
||||
init = mach + state_offset;
|
||||
firstst[init] = firstst[mach] + state_offset;
|
||||
finalst[init] = finalst[mach] + state_offset;
|
||||
lastst[init] = lastst[mach] + state_offset;
|
||||
|
||||
return init;
|
||||
}
|
||||
|
||||
|
||||
/* finish_rule - finish up the processing for a rule
|
||||
*
|
||||
* An accepting number is added to the given machine. If variable_trail_rule
|
||||
* is true then the rule has trailing context and both the head and trail
|
||||
* are variable size. Otherwise if headcnt or trailcnt is non-zero then
|
||||
* the machine recognizes a pattern with trailing context and headcnt is
|
||||
* the number of characters in the matched part of the pattern, or zero
|
||||
* if the matched part has variable length. trailcnt is the number of
|
||||
* trailing context characters in the pattern, or zero if the trailing
|
||||
* context has variable length.
|
||||
*/
|
||||
|
||||
void finish_rule (mach, variable_trail_rule, headcnt, trailcnt,
|
||||
pcont_act)
|
||||
int mach, variable_trail_rule, headcnt, trailcnt, pcont_act;
|
||||
{
|
||||
char action_text[MAXLINE];
|
||||
|
||||
add_accept (mach, num_rules);
|
||||
|
||||
/* We did this in new_rule(), but it often gets the wrong
|
||||
* number because we do it before we start parsing the current rule.
|
||||
*/
|
||||
rule_linenum[num_rules] = linenum;
|
||||
|
||||
/* If this is a continued action, then the line-number has already
|
||||
* been updated, giving us the wrong number.
|
||||
*/
|
||||
if (continued_action)
|
||||
--rule_linenum[num_rules];
|
||||
|
||||
|
||||
/* If the previous rule was continued action, then we inherit the
|
||||
* previous newline flag, possibly overriding the current one.
|
||||
*/
|
||||
if (pcont_act && rule_has_nl[num_rules - 1])
|
||||
rule_has_nl[num_rules] = true;
|
||||
|
||||
snprintf (action_text, sizeof(action_text), "case %d:\n", num_rules);
|
||||
add_action (action_text);
|
||||
if (rule_has_nl[num_rules]) {
|
||||
snprintf (action_text, sizeof(action_text), "/* rule %d can match eol */\n",
|
||||
num_rules);
|
||||
add_action (action_text);
|
||||
}
|
||||
|
||||
|
||||
if (variable_trail_rule) {
|
||||
rule_type[num_rules] = RULE_VARIABLE;
|
||||
|
||||
if (performance_report > 0)
|
||||
fprintf (stderr,
|
||||
_
|
||||
("Variable trailing context rule at line %d\n"),
|
||||
rule_linenum[num_rules]);
|
||||
|
||||
variable_trailing_context_rules = true;
|
||||
}
|
||||
|
||||
else {
|
||||
rule_type[num_rules] = RULE_NORMAL;
|
||||
|
||||
if (headcnt > 0 || trailcnt > 0) {
|
||||
/* Do trailing context magic to not match the trailing
|
||||
* characters.
|
||||
*/
|
||||
char *scanner_cp = "YY_G(yy_c_buf_p) = yy_cp";
|
||||
char *scanner_bp = "yy_bp";
|
||||
|
||||
add_action
|
||||
("*yy_cp = YY_G(yy_hold_char); /* undo effects of setting up yytext */\n");
|
||||
|
||||
if (headcnt > 0) {
|
||||
snprintf (action_text, sizeof(action_text), "%s = %s + %d;\n",
|
||||
scanner_cp, scanner_bp, headcnt);
|
||||
add_action (action_text);
|
||||
}
|
||||
|
||||
else {
|
||||
snprintf (action_text, sizeof(action_text), "%s -= %d;\n",
|
||||
scanner_cp, trailcnt);
|
||||
add_action (action_text);
|
||||
}
|
||||
|
||||
add_action
|
||||
("YY_DO_BEFORE_ACTION; /* set up yytext again */\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Okay, in the action code at this point yytext and yyleng have
|
||||
* their proper final values for this rule, so here's the point
|
||||
* to do any user action. But don't do it for continued actions,
|
||||
* as that'll result in multiple YY_RULE_SETUP's.
|
||||
*/
|
||||
if (!continued_action)
|
||||
add_action ("YY_RULE_SETUP\n");
|
||||
|
||||
line_directive_out ((FILE *) 0, 1);
|
||||
}
|
||||
|
||||
|
||||
/* link_machines - connect two machines together
|
||||
*
|
||||
* synopsis
|
||||
*
|
||||
* new = link_machines( first, last );
|
||||
*
|
||||
* new - a machine constructed by connecting first to last
|
||||
* first - the machine whose successor is to be last
|
||||
* last - the machine whose predecessor is to be first
|
||||
*
|
||||
* note: this routine concatenates the machine first with the machine
|
||||
* last to produce a machine new which will pattern-match first first
|
||||
* and then last, and will fail if either of the sub-patterns fails.
|
||||
* FIRST is set to new by the operation. last is unmolested.
|
||||
*/
|
||||
|
||||
int link_machines (first, last)
|
||||
int first, last;
|
||||
{
|
||||
if (first == NIL)
|
||||
return last;
|
||||
|
||||
else if (last == NIL)
|
||||
return first;
|
||||
|
||||
else {
|
||||
mkxtion (finalst[first], last);
|
||||
finalst[first] = finalst[last];
|
||||
lastst[first] = MAX (lastst[first], lastst[last]);
|
||||
firstst[first] = MIN (firstst[first], firstst[last]);
|
||||
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* mark_beginning_as_normal - mark each "beginning" state in a machine
|
||||
* as being a "normal" (i.e., not trailing context-
|
||||
* associated) states
|
||||
*
|
||||
* The "beginning" states are the epsilon closure of the first state
|
||||
*/
|
||||
|
||||
void mark_beginning_as_normal (mach)
|
||||
register int mach;
|
||||
{
|
||||
switch (state_type[mach]) {
|
||||
case STATE_NORMAL:
|
||||
/* Oh, we've already visited here. */
|
||||
return;
|
||||
|
||||
case STATE_TRAILING_CONTEXT:
|
||||
state_type[mach] = STATE_NORMAL;
|
||||
|
||||
if (transchar[mach] == SYM_EPSILON) {
|
||||
if (trans1[mach] != NO_TRANSITION)
|
||||
mark_beginning_as_normal (trans1[mach]);
|
||||
|
||||
if (trans2[mach] != NO_TRANSITION)
|
||||
mark_beginning_as_normal (trans2[mach]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
flexerror (_
|
||||
("bad state type in mark_beginning_as_normal()"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* mkbranch - make a machine that branches to two machines
|
||||
*
|
||||
* synopsis
|
||||
*
|
||||
* branch = mkbranch( first, second );
|
||||
*
|
||||
* branch - a machine which matches either first's pattern or second's
|
||||
* first, second - machines whose patterns are to be or'ed (the | operator)
|
||||
*
|
||||
* Note that first and second are NEITHER destroyed by the operation. Also,
|
||||
* the resulting machine CANNOT be used with any other "mk" operation except
|
||||
* more mkbranch's. Compare with mkor()
|
||||
*/
|
||||
|
||||
int mkbranch (first, second)
|
||||
int first, second;
|
||||
{
|
||||
int eps;
|
||||
|
||||
if (first == NO_TRANSITION)
|
||||
return second;
|
||||
|
||||
else if (second == NO_TRANSITION)
|
||||
return first;
|
||||
|
||||
eps = mkstate (SYM_EPSILON);
|
||||
|
||||
mkxtion (eps, first);
|
||||
mkxtion (eps, second);
|
||||
|
||||
return eps;
|
||||
}
|
||||
|
||||
|
||||
/* mkclos - convert a machine into a closure
|
||||
*
|
||||
* synopsis
|
||||
* new = mkclos( state );
|
||||
*
|
||||
* new - a new state which matches the closure of "state"
|
||||
*/
|
||||
|
||||
int mkclos (state)
|
||||
int state;
|
||||
{
|
||||
return mkopt (mkposcl (state));
|
||||
}
|
||||
|
||||
|
||||
/* mkopt - make a machine optional
|
||||
*
|
||||
* synopsis
|
||||
*
|
||||
* new = mkopt( mach );
|
||||
*
|
||||
* new - a machine which optionally matches whatever mach matched
|
||||
* mach - the machine to make optional
|
||||
*
|
||||
* notes:
|
||||
* 1. mach must be the last machine created
|
||||
* 2. mach is destroyed by the call
|
||||
*/
|
||||
|
||||
int mkopt (mach)
|
||||
int mach;
|
||||
{
|
||||
int eps;
|
||||
|
||||
if (!SUPER_FREE_EPSILON (finalst[mach])) {
|
||||
eps = mkstate (SYM_EPSILON);
|
||||
mach = link_machines (mach, eps);
|
||||
}
|
||||
|
||||
/* Can't skimp on the following if FREE_EPSILON(mach) is true because
|
||||
* some state interior to "mach" might point back to the beginning
|
||||
* for a closure.
|
||||
*/
|
||||
eps = mkstate (SYM_EPSILON);
|
||||
mach = link_machines (eps, mach);
|
||||
|
||||
mkxtion (mach, finalst[mach]);
|
||||
|
||||
return mach;
|
||||
}
|
||||
|
||||
|
||||
/* mkor - make a machine that matches either one of two machines
|
||||
*
|
||||
* synopsis
|
||||
*
|
||||
* new = mkor( first, second );
|
||||
*
|
||||
* new - a machine which matches either first's pattern or second's
|
||||
* first, second - machines whose patterns are to be or'ed (the | operator)
|
||||
*
|
||||
* note that first and second are both destroyed by the operation
|
||||
* the code is rather convoluted because an attempt is made to minimize
|
||||
* the number of epsilon states needed
|
||||
*/
|
||||
|
||||
int mkor (first, second)
|
||||
int first, second;
|
||||
{
|
||||
int eps, orend;
|
||||
|
||||
if (first == NIL)
|
||||
return second;
|
||||
|
||||
else if (second == NIL)
|
||||
return first;
|
||||
|
||||
else {
|
||||
/* See comment in mkopt() about why we can't use the first
|
||||
* state of "first" or "second" if they satisfy "FREE_EPSILON".
|
||||
*/
|
||||
eps = mkstate (SYM_EPSILON);
|
||||
|
||||
first = link_machines (eps, first);
|
||||
|
||||
mkxtion (first, second);
|
||||
|
||||
if (SUPER_FREE_EPSILON (finalst[first]) &&
|
||||
accptnum[finalst[first]] == NIL) {
|
||||
orend = finalst[first];
|
||||
mkxtion (finalst[second], orend);
|
||||
}
|
||||
|
||||
else if (SUPER_FREE_EPSILON (finalst[second]) &&
|
||||
accptnum[finalst[second]] == NIL) {
|
||||
orend = finalst[second];
|
||||
mkxtion (finalst[first], orend);
|
||||
}
|
||||
|
||||
else {
|
||||
eps = mkstate (SYM_EPSILON);
|
||||
|
||||
first = link_machines (first, eps);
|
||||
orend = finalst[first];
|
||||
|
||||
mkxtion (finalst[second], orend);
|
||||
}
|
||||
}
|
||||
|
||||
finalst[first] = orend;
|
||||
return first;
|
||||
}
|
||||
|
||||
|
||||
/* mkposcl - convert a machine into a positive closure
|
||||
*
|
||||
* synopsis
|
||||
* new = mkposcl( state );
|
||||
*
|
||||
* new - a machine matching the positive closure of "state"
|
||||
*/
|
||||
|
||||
int mkposcl (state)
|
||||
int state;
|
||||
{
|
||||
int eps;
|
||||
|
||||
if (SUPER_FREE_EPSILON (finalst[state])) {
|
||||
mkxtion (finalst[state], state);
|
||||
return state;
|
||||
}
|
||||
|
||||
else {
|
||||
eps = mkstate (SYM_EPSILON);
|
||||
mkxtion (eps, state);
|
||||
return link_machines (state, eps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* mkrep - make a replicated machine
|
||||
*
|
||||
* synopsis
|
||||
* new = mkrep( mach, lb, ub );
|
||||
*
|
||||
* new - a machine that matches whatever "mach" matched from "lb"
|
||||
* number of times to "ub" number of times
|
||||
*
|
||||
* note
|
||||
* if "ub" is INFINITE_REPEAT then "new" matches "lb" or more occurrences of "mach"
|
||||
*/
|
||||
|
||||
int mkrep (mach, lb, ub)
|
||||
int mach, lb, ub;
|
||||
{
|
||||
int base_mach, tail, copy, i;
|
||||
|
||||
base_mach = copysingl (mach, lb - 1);
|
||||
|
||||
if (ub == INFINITE_REPEAT) {
|
||||
copy = dupmachine (mach);
|
||||
mach = link_machines (mach,
|
||||
link_machines (base_mach,
|
||||
mkclos (copy)));
|
||||
}
|
||||
|
||||
else {
|
||||
tail = mkstate (SYM_EPSILON);
|
||||
|
||||
for (i = lb; i < ub; ++i) {
|
||||
copy = dupmachine (mach);
|
||||
tail = mkopt (link_machines (copy, tail));
|
||||
}
|
||||
|
||||
mach =
|
||||
link_machines (mach,
|
||||
link_machines (base_mach, tail));
|
||||
}
|
||||
|
||||
return mach;
|
||||
}
|
||||
|
||||
|
||||
/* mkstate - create a state with a transition on a given symbol
|
||||
*
|
||||
* synopsis
|
||||
*
|
||||
* state = mkstate( sym );
|
||||
*
|
||||
* state - a new state matching sym
|
||||
* sym - the symbol the new state is to have an out-transition on
|
||||
*
|
||||
* note that this routine makes new states in ascending order through the
|
||||
* state array (and increments LASTNFA accordingly). The routine DUPMACHINE
|
||||
* relies on machines being made in ascending order and that they are
|
||||
* CONTIGUOUS. Change it and you will have to rewrite DUPMACHINE (kludge
|
||||
* that it admittedly is)
|
||||
*/
|
||||
|
||||
int mkstate (sym)
|
||||
int sym;
|
||||
{
|
||||
if (++lastnfa >= current_mns) {
|
||||
if ((current_mns += MNS_INCREMENT) >= maximum_mns)
|
||||
lerrif (_
|
||||
("input rules are too complicated (>= %d NFA states)"),
|
||||
current_mns);
|
||||
|
||||
++num_reallocs;
|
||||
|
||||
firstst = reallocate_integer_array (firstst, current_mns);
|
||||
lastst = reallocate_integer_array (lastst, current_mns);
|
||||
finalst = reallocate_integer_array (finalst, current_mns);
|
||||
transchar =
|
||||
reallocate_integer_array (transchar, current_mns);
|
||||
trans1 = reallocate_integer_array (trans1, current_mns);
|
||||
trans2 = reallocate_integer_array (trans2, current_mns);
|
||||
accptnum =
|
||||
reallocate_integer_array (accptnum, current_mns);
|
||||
assoc_rule =
|
||||
reallocate_integer_array (assoc_rule, current_mns);
|
||||
state_type =
|
||||
reallocate_integer_array (state_type, current_mns);
|
||||
}
|
||||
|
||||
firstst[lastnfa] = lastnfa;
|
||||
finalst[lastnfa] = lastnfa;
|
||||
lastst[lastnfa] = lastnfa;
|
||||
transchar[lastnfa] = sym;
|
||||
trans1[lastnfa] = NO_TRANSITION;
|
||||
trans2[lastnfa] = NO_TRANSITION;
|
||||
accptnum[lastnfa] = NIL;
|
||||
assoc_rule[lastnfa] = num_rules;
|
||||
state_type[lastnfa] = current_state_type;
|
||||
|
||||
/* Fix up equivalence classes base on this transition. Note that any
|
||||
* character which has its own transition gets its own equivalence
|
||||
* class. Thus only characters which are only in character classes
|
||||
* have a chance at being in the same equivalence class. E.g. "a|b"
|
||||
* puts 'a' and 'b' into two different equivalence classes. "[ab]"
|
||||
* puts them in the same equivalence class (barring other differences
|
||||
* elsewhere in the input).
|
||||
*/
|
||||
|
||||
if (sym < 0) {
|
||||
/* We don't have to update the equivalence classes since
|
||||
* that was already done when the ccl was created for the
|
||||
* first time.
|
||||
*/
|
||||
}
|
||||
|
||||
else if (sym == SYM_EPSILON)
|
||||
++numeps;
|
||||
|
||||
else {
|
||||
check_char (sym);
|
||||
|
||||
if (useecs)
|
||||
/* Map NUL's to csize. */
|
||||
mkechar (sym ? sym : csize, nextecm, ecgroup);
|
||||
}
|
||||
|
||||
return lastnfa;
|
||||
}
|
||||
|
||||
|
||||
/* mkxtion - make a transition from one state to another
|
||||
*
|
||||
* synopsis
|
||||
*
|
||||
* mkxtion( statefrom, stateto );
|
||||
*
|
||||
* statefrom - the state from which the transition is to be made
|
||||
* stateto - the state to which the transition is to be made
|
||||
*/
|
||||
|
||||
void mkxtion (statefrom, stateto)
|
||||
int statefrom, stateto;
|
||||
{
|
||||
if (trans1[statefrom] == NO_TRANSITION)
|
||||
trans1[statefrom] = stateto;
|
||||
|
||||
else if ((transchar[statefrom] != SYM_EPSILON) ||
|
||||
(trans2[statefrom] != NO_TRANSITION))
|
||||
flexfatal (_("found too many transitions in mkxtion()"));
|
||||
|
||||
else { /* second out-transition for an epsilon state */
|
||||
++eps2;
|
||||
trans2[statefrom] = stateto;
|
||||
}
|
||||
}
|
||||
|
||||
/* new_rule - initialize for a new rule */
|
||||
|
||||
void new_rule ()
|
||||
{
|
||||
if (++num_rules >= current_max_rules) {
|
||||
++num_reallocs;
|
||||
current_max_rules += MAX_RULES_INCREMENT;
|
||||
rule_type = reallocate_integer_array (rule_type,
|
||||
current_max_rules);
|
||||
rule_linenum = reallocate_integer_array (rule_linenum,
|
||||
current_max_rules);
|
||||
rule_useful = reallocate_integer_array (rule_useful,
|
||||
current_max_rules);
|
||||
rule_has_nl = reallocate_bool_array (rule_has_nl,
|
||||
current_max_rules);
|
||||
}
|
||||
|
||||
if (num_rules > MAX_RULE)
|
||||
lerrif (_("too many rules (> %d)!"), MAX_RULE);
|
||||
|
||||
rule_linenum[num_rules] = linenum;
|
||||
rule_useful[num_rules] = false;
|
||||
rule_has_nl[num_rules] = false;
|
||||
}
|
280
contrib/flex/options.c
Normal file
280
contrib/flex/options.c
Normal file
@ -0,0 +1,280 @@
|
||||
/* flex - tool to generate fast lexical analyzers */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "options.h"
|
||||
|
||||
/* Be sure to synchronize these options with those defined in "options.h",
|
||||
* the giant switch() statement in "main.c", and the %option processing in
|
||||
* "scan.l".
|
||||
*/
|
||||
|
||||
|
||||
/* The command-line options, passed to scanopt_init() */
|
||||
optspec_t flexopts[] = {
|
||||
|
||||
{"-7", OPT_7BIT, 0}
|
||||
,
|
||||
{"--7bit", OPT_7BIT, 0}
|
||||
, /* Generate 7-bit scanner. */
|
||||
{"-8", OPT_8BIT, 0}
|
||||
,
|
||||
{"--8bit", OPT_8BIT, 0}
|
||||
, /* Generate 8-bit scanner. */
|
||||
{"--align", OPT_ALIGN, 0}
|
||||
, /* Trade off larger tables for better memory alignment. */
|
||||
{"--noalign", OPT_NO_ALIGN, 0}
|
||||
,
|
||||
{"--always-interactive", OPT_ALWAYS_INTERACTIVE, 0}
|
||||
,
|
||||
{"--array", OPT_ARRAY, 0}
|
||||
,
|
||||
{"-b", OPT_BACKUP, 0}
|
||||
,
|
||||
{"--backup", OPT_BACKUP, 0}
|
||||
, /* Generate backing-up information to lex.backup. */
|
||||
{"-B", OPT_BATCH, 0}
|
||||
,
|
||||
{"--batch", OPT_BATCH, 0}
|
||||
, /* Generate batch scanner (opposite of -I). */
|
||||
{"--bison-bridge", OPT_BISON_BRIDGE, 0}
|
||||
, /* Scanner to be called by a bison pure parser. */
|
||||
{"--bison-locations", OPT_BISON_BRIDGE_LOCATIONS, 0}
|
||||
, /* Scanner to be called by a bison pure parser. */
|
||||
{"-i", OPT_CASE_INSENSITIVE, 0}
|
||||
,
|
||||
{"--case-insensitive", OPT_CASE_INSENSITIVE, 0}
|
||||
, /* Generate case-insensitive scanner. */
|
||||
|
||||
{"-C[aefFmr]", OPT_COMPRESSION,
|
||||
"Specify degree of table compression (default is -Cem)"},
|
||||
{"-+", OPT_CPLUSPLUS, 0}
|
||||
,
|
||||
{"--c++", OPT_CPLUSPLUS, 0}
|
||||
, /* Generate C++ scanner class. */
|
||||
{"-d", OPT_DEBUG, 0}
|
||||
,
|
||||
{"--debug", OPT_DEBUG, 0}
|
||||
, /* Turn on debug mode in generated scanner. */
|
||||
{"--nodebug", OPT_NO_DEBUG, 0}
|
||||
,
|
||||
{"-s", OPT_NO_DEFAULT, 0}
|
||||
,
|
||||
{"--nodefault", OPT_NO_DEFAULT, 0}
|
||||
, /* Suppress default rule to ECHO unmatched text. */
|
||||
{"--default", OPT_DEFAULT, 0}
|
||||
,
|
||||
{"-c", OPT_DONOTHING, 0}
|
||||
, /* For POSIX lex compatibility. */
|
||||
{"-n", OPT_DONOTHING, 0}
|
||||
, /* For POSIX lex compatibility. */
|
||||
{"--ecs", OPT_ECS, 0}
|
||||
, /* Construct equivalence classes. */
|
||||
{"--noecs", OPT_NO_ECS, 0}
|
||||
,
|
||||
{"-F", OPT_FAST, 0}
|
||||
,
|
||||
{"--fast", OPT_FAST, 0}
|
||||
, /* Same as -CFr. */
|
||||
{"-f", OPT_FULL, 0}
|
||||
,
|
||||
{"--full", OPT_FULL, 0}
|
||||
, /* Same as -Cfr. */
|
||||
{"--header-file[=FILE]", OPT_HEADER_FILE, 0}
|
||||
,
|
||||
{"-?", OPT_HELP, 0}
|
||||
,
|
||||
{"-h", OPT_HELP, 0}
|
||||
,
|
||||
{"--help", OPT_HELP, 0}
|
||||
, /* Produce this help message. */
|
||||
{"-I", OPT_INTERACTIVE, 0}
|
||||
,
|
||||
{"--interactive", OPT_INTERACTIVE, 0}
|
||||
, /* Generate interactive scanner (opposite of -B). */
|
||||
{"-l", OPT_LEX_COMPAT, 0}
|
||||
,
|
||||
{"--lex-compat", OPT_LEX_COMPAT, 0}
|
||||
, /* Maximal compatibility with original lex. */
|
||||
{"-X", OPT_POSIX_COMPAT, 0}
|
||||
,
|
||||
{"--posix-compat", OPT_POSIX_COMPAT, 0}
|
||||
, /* Maximal compatibility with POSIX lex. */
|
||||
{"--preproc=NUM", OPT_PREPROC_LEVEL, 0}
|
||||
,
|
||||
{"-L", OPT_NO_LINE, 0}
|
||||
, /* Suppress #line directives in scanner. */
|
||||
{"--noline", OPT_NO_LINE, 0}
|
||||
, /* Suppress #line directives in scanner. */
|
||||
{"--main", OPT_MAIN, 0}
|
||||
, /* use built-in main() function. */
|
||||
{"--nomain", OPT_NO_MAIN, 0}
|
||||
,
|
||||
{"--meta-ecs", OPT_META_ECS, 0}
|
||||
, /* Construct meta-equivalence classes. */
|
||||
{"--nometa-ecs", OPT_NO_META_ECS, 0}
|
||||
,
|
||||
{"--never-interactive", OPT_NEVER_INTERACTIVE, 0}
|
||||
,
|
||||
{"-o FILE", OPT_OUTFILE, 0}
|
||||
,
|
||||
{"--outfile=FILE", OPT_OUTFILE, 0}
|
||||
, /* Write to FILE (default is lex.yy.c) */
|
||||
{"-p", OPT_PERF_REPORT, 0}
|
||||
,
|
||||
{"--perf-report", OPT_PERF_REPORT, 0}
|
||||
, /* Generate performance report to stderr. */
|
||||
{"--pointer", OPT_POINTER, 0}
|
||||
,
|
||||
{"-P PREFIX", OPT_PREFIX, 0}
|
||||
,
|
||||
{"--prefix=PREFIX", OPT_PREFIX, 0}
|
||||
, /* Use PREFIX (default is yy) */
|
||||
{"-Dmacro", OPT_PREPROCDEFINE, 0}
|
||||
, /* Define a preprocessor symbol. */
|
||||
{"--read", OPT_READ, 0}
|
||||
, /* Use read(2) instead of stdio. */
|
||||
{"-R", OPT_REENTRANT, 0}
|
||||
,
|
||||
{"--reentrant", OPT_REENTRANT, 0}
|
||||
, /* Generate a reentrant C scanner. */
|
||||
{"--noreentrant", OPT_NO_REENTRANT, 0}
|
||||
,
|
||||
{"--reject", OPT_REJECT, 0}
|
||||
,
|
||||
{"--noreject", OPT_NO_REJECT, 0}
|
||||
,
|
||||
{"-S FILE", OPT_SKEL, 0}
|
||||
,
|
||||
{"--skel=FILE", OPT_SKEL, 0}
|
||||
, /* Use skeleton from FILE */
|
||||
{"--stack", OPT_STACK, 0}
|
||||
,
|
||||
{"--stdinit", OPT_STDINIT, 0}
|
||||
,
|
||||
{"--nostdinit", OPT_NO_STDINIT, 0}
|
||||
,
|
||||
{"-t", OPT_STDOUT, 0}
|
||||
,
|
||||
{"--stdout", OPT_STDOUT, 0}
|
||||
, /* Write generated scanner to stdout. */
|
||||
{"-T", OPT_TRACE, 0}
|
||||
,
|
||||
{"--trace", OPT_TRACE, 0}
|
||||
, /* Flex should run in trace mode. */
|
||||
{"--tables-file[=FILE]", OPT_TABLES_FILE, 0}
|
||||
, /* Save tables to FILE */
|
||||
{"--tables-verify", OPT_TABLES_VERIFY, 0}
|
||||
, /* Tables integrity check */
|
||||
{"--nounistd", OPT_NO_UNISTD_H, 0}
|
||||
, /* Do not include unistd.h */
|
||||
{"-v", OPT_VERBOSE, 0}
|
||||
,
|
||||
{"--verbose", OPT_VERBOSE, 0}
|
||||
, /* Write summary of scanner statistics to stdout. */
|
||||
{"-V", OPT_VERSION, 0}
|
||||
,
|
||||
{"--version", OPT_VERSION, 0}
|
||||
, /* Report flex version. */
|
||||
{"--warn", OPT_WARN, 0}
|
||||
,
|
||||
{"-w", OPT_NO_WARN, 0}
|
||||
,
|
||||
{"--nowarn", OPT_NO_WARN, 0}
|
||||
, /* Suppress warning messages. */
|
||||
{"--noansi-definitions", OPT_NO_ANSI_FUNC_DEFS, 0}
|
||||
,
|
||||
{"--noansi-prototypes", OPT_NO_ANSI_FUNC_PROTOS, 0}
|
||||
,
|
||||
{"--yyclass=NAME", OPT_YYCLASS, 0}
|
||||
,
|
||||
{"--yylineno", OPT_YYLINENO, 0}
|
||||
,
|
||||
{"--noyylineno", OPT_NO_YYLINENO, 0}
|
||||
,
|
||||
|
||||
{"--yymore", OPT_YYMORE, 0}
|
||||
,
|
||||
{"--noyymore", OPT_NO_YYMORE, 0}
|
||||
,
|
||||
{"--noyywrap", OPT_NO_YYWRAP, 0}
|
||||
,
|
||||
{"--yywrap", OPT_YYWRAP, 0}
|
||||
,
|
||||
|
||||
{"--nounput", OPT_NO_UNPUT, 0}
|
||||
,
|
||||
{"--noyy_push_state", OPT_NO_YY_PUSH_STATE, 0}
|
||||
,
|
||||
{"--noyy_pop_state", OPT_NO_YY_POP_STATE, 0}
|
||||
,
|
||||
{"--noyy_top_state", OPT_NO_YY_TOP_STATE, 0}
|
||||
,
|
||||
{"--noyy_scan_buffer", OPT_NO_YY_SCAN_BUFFER, 0}
|
||||
,
|
||||
{"--noyy_scan_bytes", OPT_NO_YY_SCAN_BYTES, 0}
|
||||
,
|
||||
{"--noyy_scan_string", OPT_NO_YY_SCAN_STRING, 0}
|
||||
,
|
||||
{"--noyyget_extra", OPT_NO_YYGET_EXTRA, 0}
|
||||
,
|
||||
{"--noyyset_extra", OPT_NO_YYSET_EXTRA, 0}
|
||||
,
|
||||
{"--noyyget_leng", OPT_NO_YYGET_LENG, 0}
|
||||
,
|
||||
{"--noyyget_text", OPT_NO_YYGET_TEXT, 0}
|
||||
,
|
||||
{"--noyyget_lineno", OPT_NO_YYGET_LINENO, 0}
|
||||
,
|
||||
{"--noyyset_lineno", OPT_NO_YYSET_LINENO, 0}
|
||||
,
|
||||
{"--noyyget_in", OPT_NO_YYGET_IN, 0}
|
||||
,
|
||||
{"--noyyset_in", OPT_NO_YYSET_IN, 0}
|
||||
,
|
||||
{"--noyyget_out", OPT_NO_YYGET_OUT, 0}
|
||||
,
|
||||
{"--noyyset_out", OPT_NO_YYSET_OUT, 0}
|
||||
,
|
||||
{"--noyyget_lval", OPT_NO_YYGET_LVAL, 0}
|
||||
,
|
||||
{"--noyyset_lval", OPT_NO_YYSET_LVAL, 0}
|
||||
,
|
||||
{"--noyyget_lloc", OPT_NO_YYGET_LLOC, 0}
|
||||
,
|
||||
{"--noyyset_lloc", OPT_NO_YYSET_LLOC, 0}
|
||||
,
|
||||
|
||||
{0, 0, 0} /* required final NULL entry. */
|
||||
};
|
||||
|
||||
/* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */
|
134
contrib/flex/options.h
Normal file
134
contrib/flex/options.h
Normal file
@ -0,0 +1,134 @@
|
||||
/* flex - tool to generate fast lexical analyzers */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#ifndef OPTIONS_H
|
||||
#define OPTIONS_H
|
||||
#include "scanopt.h"
|
||||
|
||||
extern optspec_t flexopts[];
|
||||
|
||||
enum flexopt_flag_t {
|
||||
/* Use positive integers only, since they are return codes for scanopt.
|
||||
* Order is not important. */
|
||||
OPT_7BIT = 1,
|
||||
OPT_8BIT,
|
||||
OPT_ALIGN,
|
||||
OPT_ALWAYS_INTERACTIVE,
|
||||
OPT_ARRAY,
|
||||
OPT_BACKUP,
|
||||
OPT_BATCH,
|
||||
OPT_BISON_BRIDGE,
|
||||
OPT_BISON_BRIDGE_LOCATIONS,
|
||||
OPT_CASE_INSENSITIVE,
|
||||
OPT_COMPRESSION,
|
||||
OPT_CPLUSPLUS,
|
||||
OPT_DEBUG,
|
||||
OPT_DEFAULT,
|
||||
OPT_DONOTHING,
|
||||
OPT_ECS,
|
||||
OPT_FAST,
|
||||
OPT_FULL,
|
||||
OPT_HEADER_FILE,
|
||||
OPT_HELP,
|
||||
OPT_INTERACTIVE,
|
||||
OPT_LEX_COMPAT,
|
||||
OPT_POSIX_COMPAT,
|
||||
OPT_MAIN,
|
||||
OPT_META_ECS,
|
||||
OPT_NEVER_INTERACTIVE,
|
||||
OPT_NO_ALIGN,
|
||||
OPT_NO_ANSI_FUNC_DEFS,
|
||||
OPT_NO_ANSI_FUNC_PROTOS,
|
||||
OPT_NO_DEBUG,
|
||||
OPT_NO_DEFAULT,
|
||||
OPT_NO_ECS,
|
||||
OPT_NO_LINE,
|
||||
OPT_NO_MAIN,
|
||||
OPT_NO_META_ECS,
|
||||
OPT_NO_REENTRANT,
|
||||
OPT_NO_REJECT,
|
||||
OPT_NO_STDINIT,
|
||||
OPT_NO_UNPUT,
|
||||
OPT_NO_WARN,
|
||||
OPT_NO_YYGET_EXTRA,
|
||||
OPT_NO_YYGET_IN,
|
||||
OPT_NO_YYGET_LENG,
|
||||
OPT_NO_YYGET_LINENO,
|
||||
OPT_NO_YYGET_LLOC,
|
||||
OPT_NO_YYGET_LVAL,
|
||||
OPT_NO_YYGET_OUT,
|
||||
OPT_NO_YYGET_TEXT,
|
||||
OPT_NO_YYLINENO,
|
||||
OPT_NO_YYMORE,
|
||||
OPT_NO_YYSET_EXTRA,
|
||||
OPT_NO_YYSET_IN,
|
||||
OPT_NO_YYSET_LINENO,
|
||||
OPT_NO_YYSET_LLOC,
|
||||
OPT_NO_YYSET_LVAL,
|
||||
OPT_NO_YYSET_OUT,
|
||||
OPT_NO_YYWRAP,
|
||||
OPT_NO_YY_POP_STATE,
|
||||
OPT_NO_YY_PUSH_STATE,
|
||||
OPT_NO_YY_SCAN_BUFFER,
|
||||
OPT_NO_YY_SCAN_BYTES,
|
||||
OPT_NO_YY_SCAN_STRING,
|
||||
OPT_NO_YY_TOP_STATE,
|
||||
OPT_OUTFILE,
|
||||
OPT_PERF_REPORT,
|
||||
OPT_POINTER,
|
||||
OPT_PREFIX,
|
||||
OPT_PREPROCDEFINE,
|
||||
OPT_PREPROC_LEVEL,
|
||||
OPT_READ,
|
||||
OPT_REENTRANT,
|
||||
OPT_REJECT,
|
||||
OPT_SKEL,
|
||||
OPT_STACK,
|
||||
OPT_STDINIT,
|
||||
OPT_STDOUT,
|
||||
OPT_TABLES_FILE,
|
||||
OPT_TABLES_VERIFY,
|
||||
OPT_TRACE,
|
||||
OPT_NO_UNISTD_H,
|
||||
OPT_VERBOSE,
|
||||
OPT_VERSION,
|
||||
OPT_WARN,
|
||||
OPT_YYCLASS,
|
||||
OPT_YYLINENO,
|
||||
OPT_YYMORE,
|
||||
OPT_YYWRAP
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* vim:set tabstop=8 softtabstop=4 shiftwidth=4 textwidth=0: */
|
1089
contrib/flex/parse.y
Normal file
1089
contrib/flex/parse.y
Normal file
File diff suppressed because it is too large
Load Diff
172
contrib/flex/regex.c
Normal file
172
contrib/flex/regex.c
Normal file
@ -0,0 +1,172 @@
|
||||
/** regex - regular expression functions related to POSIX regex lib. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
|
||||
static const char* REGEXP_LINEDIR = "^#line ([[:digit:]]+) \"(.*)\"";
|
||||
static const char* REGEXP_BLANK_LINE = "^[[:space:]]*$";
|
||||
|
||||
regex_t regex_linedir; /**< matches line directives */
|
||||
regex_t regex_blank_line; /**< matches blank lines */
|
||||
|
||||
|
||||
/** Initialize the regular expressions.
|
||||
* @return true upon success.
|
||||
*/
|
||||
bool flex_init_regex(void)
|
||||
{
|
||||
flex_regcomp(®ex_linedir, REGEXP_LINEDIR, REG_EXTENDED);
|
||||
flex_regcomp(®ex_blank_line, REGEXP_BLANK_LINE, REG_EXTENDED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Compiles a regular expression or dies trying.
|
||||
* @param preg Same as for regcomp().
|
||||
* @param regex Same as for regcomp().
|
||||
* @param cflags Same as for regcomp().
|
||||
*/
|
||||
void flex_regcomp(regex_t *preg, const char *regex, int cflags)
|
||||
{
|
||||
int err;
|
||||
|
||||
memset (preg, 0, sizeof (regex_t));
|
||||
|
||||
if ((err = regcomp (preg, regex, cflags)) != 0) {
|
||||
const int errbuf_sz = 200;
|
||||
char *errbuf, *rxerr;
|
||||
|
||||
errbuf = (char*)flex_alloc(errbuf_sz *sizeof(char));
|
||||
if (!errbuf)
|
||||
flexfatal(_("Unable to allocate buffer to report regcomp"));
|
||||
rxerr = (char*)flex_alloc(errbuf_sz *sizeof(char));
|
||||
if (!rxerr)
|
||||
flexfatal(_("Unable to allocate buffer for regerror"));
|
||||
regerror (err, preg, rxerr, errbuf_sz);
|
||||
snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr);
|
||||
|
||||
flexfatal (errbuf);
|
||||
free(errbuf);
|
||||
free(rxerr);
|
||||
}
|
||||
}
|
||||
|
||||
/** Extract a copy of the match, or NULL if no match.
|
||||
* @param m A match as returned by regexec().
|
||||
* @param src The source string that was passed to regexec().
|
||||
* @return The allocated string.
|
||||
*/
|
||||
char *regmatch_dup (regmatch_t * m, const char *src)
|
||||
{
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
if (m == NULL || m->rm_so < 0)
|
||||
return NULL;
|
||||
len = m->rm_eo - m->rm_so;
|
||||
str = (char *) flex_alloc ((len + 1) * sizeof (char));
|
||||
if (!str)
|
||||
flexfatal(_("Unable to allocate a copy of the match"));
|
||||
strncpy (str, src + m->rm_so, len);
|
||||
str[len] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/** Copy the match.
|
||||
* @param m A match as returned by regexec().
|
||||
* @param dest The destination buffer.
|
||||
* @param src The source string that was passed to regexec().
|
||||
* @return dest
|
||||
*/
|
||||
char *regmatch_cpy (regmatch_t * m, char *dest, const char *src)
|
||||
{
|
||||
if (m == NULL || m->rm_so < 0) {
|
||||
if (dest)
|
||||
dest[0] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
snprintf (dest, regmatch_len(m), "%s", src + m->rm_so);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/** Get the length in characters of the match.
|
||||
* @param m A match as returned by regexec().
|
||||
* @param src The source string that was passed to regexec().
|
||||
* @return The length of the match.
|
||||
*/
|
||||
int regmatch_len (regmatch_t * m)
|
||||
{
|
||||
if (m == NULL || m->rm_so < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m->rm_eo - m->rm_so;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Convert a regmatch_t object to an integer using the strtol() function.
|
||||
* @param m A match as returned by regexec().
|
||||
* @param src The source string that was passed to regexec().
|
||||
* @param endptr Same as the second argument to strtol().
|
||||
* @param base Same as the third argument to strtol().
|
||||
* @return The converted integer or error (Return value is the same as for strtol()).
|
||||
*/
|
||||
int regmatch_strtol (regmatch_t * m, const char *src, char **endptr,
|
||||
int base)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
#define bufsz 20
|
||||
char buf[bufsz];
|
||||
char *s;
|
||||
|
||||
if (m == NULL || m->rm_so < 0)
|
||||
return 0;
|
||||
|
||||
if (regmatch_len (m) < bufsz)
|
||||
s = regmatch_cpy (m, buf, src);
|
||||
else
|
||||
s = regmatch_dup (m, src);
|
||||
|
||||
n = strtol (s, endptr, base);
|
||||
|
||||
if (s != buf)
|
||||
free (s);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Check for empty or non-existent match.
|
||||
* @param m A match as returned by regexec().
|
||||
* @return false if match length is non-zero.
|
||||
* Note that reg_empty returns true even if match did not occur at all.
|
||||
*/
|
||||
bool regmatch_empty (regmatch_t * m)
|
||||
{
|
||||
return (m == NULL || m->rm_so < 0 || m->rm_so == m->rm_eo);
|
||||
}
|
||||
|
||||
/* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */
|
1029
contrib/flex/scan.l
Normal file
1029
contrib/flex/scan.l
Normal file
File diff suppressed because it is too large
Load Diff
69
contrib/flex/scanflags.c
Normal file
69
contrib/flex/scanflags.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* scanflags - flags used by scanning. */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
scanflags_t* _sf_stk = NULL;
|
||||
size_t _sf_top_ix=0, _sf_max=0;
|
||||
|
||||
void
|
||||
sf_push (void)
|
||||
{
|
||||
if (_sf_top_ix + 1 >= _sf_max)
|
||||
_sf_stk = (scanflags_t*) flex_realloc ( (void*) _sf_stk, sizeof(scanflags_t) * (_sf_max += 32));
|
||||
|
||||
// copy the top element
|
||||
_sf_stk[_sf_top_ix + 1] = _sf_stk[_sf_top_ix];
|
||||
++_sf_top_ix;
|
||||
}
|
||||
|
||||
void
|
||||
sf_pop (void)
|
||||
{
|
||||
assert(_sf_top_ix > 0);
|
||||
--_sf_top_ix;
|
||||
}
|
||||
|
||||
/* one-time initialization. Should be called before any sf_ functions. */
|
||||
void
|
||||
sf_init (void)
|
||||
{
|
||||
assert(_sf_stk == NULL);
|
||||
_sf_stk = (scanflags_t*) flex_alloc ( sizeof(scanflags_t) * (_sf_max = 32));
|
||||
if (!_sf_stk)
|
||||
lerrsf_fatal(_("Unable to allocate %ld of stack"),
|
||||
(long)sizeof(scanflags_t));
|
||||
_sf_stk[_sf_top_ix] = 0;
|
||||
}
|
||||
|
||||
/* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */
|
873
contrib/flex/scanopt.c
Normal file
873
contrib/flex/scanopt.c
Normal file
@ -0,0 +1,873 @@
|
||||
/* flex - tool to generate fast lexical analyzers */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
#include "scanopt.h"
|
||||
|
||||
|
||||
/* Internal structures */
|
||||
|
||||
#ifdef HAVE_STRCASECMP
|
||||
#define STRCASECMP(a,b) strcasecmp(a,b)
|
||||
#else
|
||||
static int STRCASECMP PROTO ((const char *, const char *));
|
||||
|
||||
static int STRCASECMP (a, b)
|
||||
const char *a;
|
||||
const char *b;
|
||||
{
|
||||
while (tolower (*a++) == tolower (*b++)) ;
|
||||
return b - a;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ARG_NONE 0x01
|
||||
#define ARG_REQ 0x02
|
||||
#define ARG_OPT 0x04
|
||||
#define IS_LONG 0x08
|
||||
|
||||
struct _aux {
|
||||
int flags; /* The above hex flags. */
|
||||
int namelen; /* Length of the actual option word, e.g., "--file[=foo]" is 4 */
|
||||
int printlen; /* Length of entire string, e.g., "--file[=foo]" is 12 */
|
||||
};
|
||||
|
||||
|
||||
struct _scanopt_t {
|
||||
const optspec_t *options; /* List of options. */
|
||||
struct _aux *aux; /* Auxiliary data about options. */
|
||||
int optc; /* Number of options. */
|
||||
int argc; /* Number of args. */
|
||||
char **argv; /* Array of strings. */
|
||||
int index; /* Used as: argv[index][subscript]. */
|
||||
int subscript;
|
||||
char no_err_msg; /* If true, do not print errors. */
|
||||
char has_long;
|
||||
char has_short;
|
||||
};
|
||||
|
||||
/* Accessor functions. These WOULD be one-liners, but portability calls. */
|
||||
static const char *NAME PROTO ((struct _scanopt_t *, int));
|
||||
static int PRINTLEN PROTO ((struct _scanopt_t *, int));
|
||||
static int RVAL PROTO ((struct _scanopt_t *, int));
|
||||
static int FLAGS PROTO ((struct _scanopt_t *, int));
|
||||
static const char *DESC PROTO ((struct _scanopt_t *, int));
|
||||
static int scanopt_err PROTO ((struct _scanopt_t *, int, int, int));
|
||||
static int matchlongopt PROTO ((char *, char **, int *, char **, int *));
|
||||
static int find_opt
|
||||
PROTO ((struct _scanopt_t *, int, char *, int, int *, int *opt_offset));
|
||||
|
||||
static const char *NAME (s, i)
|
||||
struct _scanopt_t *s;
|
||||
int i;
|
||||
{
|
||||
return s->options[i].opt_fmt +
|
||||
((s->aux[i].flags & IS_LONG) ? 2 : 1);
|
||||
}
|
||||
|
||||
static int PRINTLEN (s, i)
|
||||
struct _scanopt_t *s;
|
||||
int i;
|
||||
{
|
||||
return s->aux[i].printlen;
|
||||
}
|
||||
|
||||
static int RVAL (s, i)
|
||||
struct _scanopt_t *s;
|
||||
int i;
|
||||
{
|
||||
return s->options[i].r_val;
|
||||
}
|
||||
|
||||
static int FLAGS (s, i)
|
||||
struct _scanopt_t *s;
|
||||
int i;
|
||||
{
|
||||
return s->aux[i].flags;
|
||||
}
|
||||
|
||||
static const char *DESC (s, i)
|
||||
struct _scanopt_t *s;
|
||||
int i;
|
||||
{
|
||||
return s->options[i].desc ? s->options[i].desc : "";
|
||||
}
|
||||
|
||||
#ifndef NO_SCANOPT_USAGE
|
||||
static int get_cols PROTO ((void));
|
||||
|
||||
static int get_cols ()
|
||||
{
|
||||
char *env;
|
||||
int cols = 80; /* default */
|
||||
|
||||
#ifdef HAVE_NCURSES_H
|
||||
initscr ();
|
||||
endwin ();
|
||||
if (COLS > 0)
|
||||
return COLS;
|
||||
#endif
|
||||
|
||||
if ((env = getenv ("COLUMNS")) != NULL)
|
||||
cols = atoi (env);
|
||||
|
||||
return cols;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Macro to check for NULL before assigning a value. */
|
||||
#define SAFE_ASSIGN(ptr,val) \
|
||||
do{ \
|
||||
if((ptr)!=NULL) \
|
||||
*(ptr) = val; \
|
||||
}while(0)
|
||||
|
||||
/* Macro to assure we reset subscript whenever we adjust s->index.*/
|
||||
#define INC_INDEX(s,n) \
|
||||
do{ \
|
||||
(s)->index += (n); \
|
||||
(s)->subscript= 0; \
|
||||
}while(0)
|
||||
|
||||
scanopt_t *scanopt_init (options, argc, argv, flags)
|
||||
const optspec_t *options;
|
||||
int argc;
|
||||
char **argv;
|
||||
int flags;
|
||||
{
|
||||
int i;
|
||||
struct _scanopt_t *s;
|
||||
s = (struct _scanopt_t *) malloc (sizeof (struct _scanopt_t));
|
||||
|
||||
s->options = options;
|
||||
s->optc = 0;
|
||||
s->argc = argc;
|
||||
s->argv = (char **) argv;
|
||||
s->index = 1;
|
||||
s->subscript = 0;
|
||||
s->no_err_msg = (flags & SCANOPT_NO_ERR_MSG);
|
||||
s->has_long = 0;
|
||||
s->has_short = 0;
|
||||
|
||||
/* Determine option count. (Find entry with all zeros). */
|
||||
s->optc = 0;
|
||||
while (options[s->optc].opt_fmt
|
||||
|| options[s->optc].r_val || options[s->optc].desc)
|
||||
s->optc++;
|
||||
|
||||
/* Build auxiliary data */
|
||||
s->aux = (struct _aux *) malloc (s->optc * sizeof (struct _aux));
|
||||
|
||||
for (i = 0; i < s->optc; i++) {
|
||||
const Char *p, *pname;
|
||||
const struct optspec_t *opt;
|
||||
struct _aux *aux;
|
||||
|
||||
opt = s->options + i;
|
||||
aux = s->aux + i;
|
||||
|
||||
aux->flags = ARG_NONE;
|
||||
|
||||
if (opt->opt_fmt[0] == '-' && opt->opt_fmt[1] == '-') {
|
||||
aux->flags |= IS_LONG;
|
||||
pname = (const Char *)(opt->opt_fmt + 2);
|
||||
s->has_long = 1;
|
||||
}
|
||||
else {
|
||||
pname = (const Char *)(opt->opt_fmt + 1);
|
||||
s->has_short = 1;
|
||||
}
|
||||
aux->printlen = strlen (opt->opt_fmt);
|
||||
|
||||
aux->namelen = 0;
|
||||
for (p = pname + 1; *p; p++) {
|
||||
/* detect required arg */
|
||||
if (*p == '=' || isspace (*p)
|
||||
|| !(aux->flags & IS_LONG)) {
|
||||
if (aux->namelen == 0)
|
||||
aux->namelen = p - pname;
|
||||
aux->flags |= ARG_REQ;
|
||||
aux->flags &= ~ARG_NONE;
|
||||
}
|
||||
/* detect optional arg. This overrides required arg. */
|
||||
if (*p == '[') {
|
||||
if (aux->namelen == 0)
|
||||
aux->namelen = p - pname;
|
||||
aux->flags &= ~(ARG_REQ | ARG_NONE);
|
||||
aux->flags |= ARG_OPT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aux->namelen == 0)
|
||||
aux->namelen = p - pname;
|
||||
}
|
||||
return (scanopt_t *) s;
|
||||
}
|
||||
|
||||
#ifndef NO_SCANOPT_USAGE
|
||||
/* these structs are for scanopt_usage(). */
|
||||
struct usg_elem {
|
||||
int idx;
|
||||
struct usg_elem *next;
|
||||
struct usg_elem *alias;
|
||||
};
|
||||
typedef struct usg_elem usg_elem;
|
||||
|
||||
|
||||
/* Prints a usage message based on contents of optlist.
|
||||
* Parameters:
|
||||
* scanner - The scanner, already initialized with scanopt_init().
|
||||
* fp - The file stream to write to.
|
||||
* usage - Text to be prepended to option list.
|
||||
* Return: Always returns 0 (zero).
|
||||
* The output looks something like this:
|
||||
|
||||
[indent][option, alias1, alias2...][indent][description line1
|
||||
description line2...]
|
||||
*/
|
||||
int scanopt_usage (scanner, fp, usage)
|
||||
scanopt_t *scanner;
|
||||
FILE *fp;
|
||||
const char *usage;
|
||||
{
|
||||
struct _scanopt_t *s;
|
||||
int i, columns, indent = 2;
|
||||
usg_elem *byr_val = NULL; /* option indices sorted by r_val */
|
||||
usg_elem *store; /* array of preallocated elements. */
|
||||
int store_idx = 0;
|
||||
usg_elem *ue;
|
||||
int maxlen[2];
|
||||
int desccol = 0;
|
||||
int print_run = 0;
|
||||
|
||||
maxlen[0] = 0;
|
||||
maxlen[1] = 0;
|
||||
|
||||
s = (struct _scanopt_t *) scanner;
|
||||
|
||||
if (usage) {
|
||||
fprintf (fp, "%s\n", usage);
|
||||
}
|
||||
else {
|
||||
/* Find the basename of argv[0] */
|
||||
const char *p;
|
||||
|
||||
p = s->argv[0] + strlen (s->argv[0]);
|
||||
while (p != s->argv[0] && *p != '/')
|
||||
--p;
|
||||
if (*p == '/')
|
||||
p++;
|
||||
|
||||
fprintf (fp, _("Usage: %s [OPTIONS]...\n"), p);
|
||||
}
|
||||
fprintf (fp, "\n");
|
||||
|
||||
/* Sort by r_val and string. Yes, this is O(n*n), but n is small. */
|
||||
store = (usg_elem *) malloc (s->optc * sizeof (usg_elem));
|
||||
for (i = 0; i < s->optc; i++) {
|
||||
|
||||
/* grab the next preallocate node. */
|
||||
ue = store + store_idx++;
|
||||
ue->idx = i;
|
||||
ue->next = ue->alias = NULL;
|
||||
|
||||
/* insert into list. */
|
||||
if (!byr_val)
|
||||
byr_val = ue;
|
||||
else {
|
||||
int found_alias = 0;
|
||||
usg_elem **ue_curr, **ptr_if_no_alias = NULL;
|
||||
|
||||
ue_curr = &byr_val;
|
||||
while (*ue_curr) {
|
||||
if (RVAL (s, (*ue_curr)->idx) ==
|
||||
RVAL (s, ue->idx)) {
|
||||
/* push onto the alias list. */
|
||||
ue_curr = &((*ue_curr)->alias);
|
||||
found_alias = 1;
|
||||
break;
|
||||
}
|
||||
if (!ptr_if_no_alias
|
||||
&&
|
||||
STRCASECMP (NAME (s, (*ue_curr)->idx),
|
||||
NAME (s, ue->idx)) > 0) {
|
||||
ptr_if_no_alias = ue_curr;
|
||||
}
|
||||
ue_curr = &((*ue_curr)->next);
|
||||
}
|
||||
if (!found_alias && ptr_if_no_alias)
|
||||
ue_curr = ptr_if_no_alias;
|
||||
ue->next = *ue_curr;
|
||||
*ue_curr = ue;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (1) {
|
||||
printf ("ORIGINAL:\n");
|
||||
for (i = 0; i < s->optc; i++)
|
||||
printf ("%2d: %s\n", i, NAME (s, i));
|
||||
printf ("SORTED:\n");
|
||||
ue = byr_val;
|
||||
while (ue) {
|
||||
usg_elem *ue2;
|
||||
|
||||
printf ("%2d: %s\n", ue->idx, NAME (s, ue->idx));
|
||||
for (ue2 = ue->alias; ue2; ue2 = ue2->next)
|
||||
printf (" +---> %2d: %s\n", ue2->idx,
|
||||
NAME (s, ue2->idx));
|
||||
ue = ue->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now build each row of output. */
|
||||
|
||||
/* first pass calculate how much room we need. */
|
||||
for (ue = byr_val; ue; ue = ue->next) {
|
||||
usg_elem *ap;
|
||||
int len = 0;
|
||||
int nshort = 0, nlong = 0;
|
||||
|
||||
|
||||
#define CALC_LEN(i) do {\
|
||||
if(FLAGS(s,i) & IS_LONG) \
|
||||
len += (nlong++||nshort) ? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\
|
||||
else\
|
||||
len += (nshort++||nlong)? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\
|
||||
}while(0)
|
||||
|
||||
if (!(FLAGS (s, ue->idx) & IS_LONG))
|
||||
CALC_LEN (ue->idx);
|
||||
|
||||
/* do short aliases first. */
|
||||
for (ap = ue->alias; ap; ap = ap->next) {
|
||||
if (FLAGS (s, ap->idx) & IS_LONG)
|
||||
continue;
|
||||
CALC_LEN (ap->idx);
|
||||
}
|
||||
|
||||
if (FLAGS (s, ue->idx) & IS_LONG)
|
||||
CALC_LEN (ue->idx);
|
||||
|
||||
/* repeat the above loop, this time for long aliases. */
|
||||
for (ap = ue->alias; ap; ap = ap->next) {
|
||||
if (!(FLAGS (s, ap->idx) & IS_LONG))
|
||||
continue;
|
||||
CALC_LEN (ap->idx);
|
||||
}
|
||||
|
||||
if (len > maxlen[0])
|
||||
maxlen[0] = len;
|
||||
|
||||
/* It's much easier to calculate length for description column! */
|
||||
len = strlen (DESC (s, ue->idx));
|
||||
if (len > maxlen[1])
|
||||
maxlen[1] = len;
|
||||
}
|
||||
|
||||
/* Determine how much room we have, and how much we will allocate to each col.
|
||||
* Do not address pathological cases. Output will just be ugly. */
|
||||
columns = get_cols () - 1;
|
||||
if (maxlen[0] + maxlen[1] + indent * 2 > columns) {
|
||||
/* col 0 gets whatever it wants. we'll wrap the desc col. */
|
||||
maxlen[1] = columns - (maxlen[0] + indent * 2);
|
||||
if (maxlen[1] < 14) /* 14 is arbitrary lower limit on desc width. */
|
||||
maxlen[1] = INT_MAX;
|
||||
}
|
||||
desccol = maxlen[0] + indent * 2;
|
||||
|
||||
#define PRINT_SPACES(fp,n)\
|
||||
do{\
|
||||
int _n;\
|
||||
_n=(n);\
|
||||
while(_n-- > 0)\
|
||||
fputc(' ',(fp));\
|
||||
}while(0)
|
||||
|
||||
|
||||
/* Second pass (same as above loop), this time we print. */
|
||||
/* Sloppy hack: We iterate twice. The first time we print short and long options.
|
||||
The second time we print those lines that have ONLY long options. */
|
||||
while (print_run++ < 2) {
|
||||
for (ue = byr_val; ue; ue = ue->next) {
|
||||
usg_elem *ap;
|
||||
int nwords = 0, nchars = 0, has_short = 0;
|
||||
|
||||
/* TODO: get has_short schtick to work */
|
||||
has_short = !(FLAGS (s, ue->idx) & IS_LONG);
|
||||
for (ap = ue->alias; ap; ap = ap->next) {
|
||||
if (!(FLAGS (s, ap->idx) & IS_LONG)) {
|
||||
has_short = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((print_run == 1 && !has_short) ||
|
||||
(print_run == 2 && has_short))
|
||||
continue;
|
||||
|
||||
PRINT_SPACES (fp, indent);
|
||||
nchars += indent;
|
||||
|
||||
/* Print, adding a ", " between aliases. */
|
||||
#define PRINT_IT(i) do{\
|
||||
if(nwords++)\
|
||||
nchars+=fprintf(fp,", ");\
|
||||
nchars+=fprintf(fp,"%s",s->options[i].opt_fmt);\
|
||||
}while(0)
|
||||
|
||||
if (!(FLAGS (s, ue->idx) & IS_LONG))
|
||||
PRINT_IT (ue->idx);
|
||||
|
||||
/* print short aliases first. */
|
||||
for (ap = ue->alias; ap; ap = ap->next) {
|
||||
if (!(FLAGS (s, ap->idx) & IS_LONG))
|
||||
PRINT_IT (ap->idx);
|
||||
}
|
||||
|
||||
|
||||
if (FLAGS (s, ue->idx) & IS_LONG)
|
||||
PRINT_IT (ue->idx);
|
||||
|
||||
/* repeat the above loop, this time for long aliases. */
|
||||
for (ap = ue->alias; ap; ap = ap->next) {
|
||||
if (FLAGS (s, ap->idx) & IS_LONG)
|
||||
PRINT_IT (ap->idx);
|
||||
}
|
||||
|
||||
/* pad to desccol */
|
||||
PRINT_SPACES (fp, desccol - nchars);
|
||||
|
||||
/* Print description, wrapped to maxlen[1] columns. */
|
||||
if (1) {
|
||||
const char *pstart;
|
||||
|
||||
pstart = DESC (s, ue->idx);
|
||||
while (1) {
|
||||
int n = 0;
|
||||
const char *lastws = NULL, *p;
|
||||
|
||||
p = pstart;
|
||||
|
||||
while (*p && n < maxlen[1]
|
||||
&& *p != '\n') {
|
||||
if (isspace ((Char)(*p))
|
||||
|| *p == '-') lastws =
|
||||
p;
|
||||
n++;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (!*p) { /* hit end of desc. done. */
|
||||
fprintf (fp, "%s\n",
|
||||
pstart);
|
||||
break;
|
||||
}
|
||||
else if (*p == '\n') { /* print everything up to here then wrap. */
|
||||
fprintf (fp, "%.*s\n", n,
|
||||
pstart);
|
||||
PRINT_SPACES (fp, desccol);
|
||||
pstart = p + 1;
|
||||
continue;
|
||||
}
|
||||
else { /* we hit the edge of the screen. wrap at space if possible. */
|
||||
if (lastws) {
|
||||
fprintf (fp,
|
||||
"%.*s\n",
|
||||
(int)(lastws - pstart),
|
||||
pstart);
|
||||
pstart =
|
||||
lastws + 1;
|
||||
}
|
||||
else {
|
||||
fprintf (fp,
|
||||
"%.*s\n",
|
||||
n,
|
||||
pstart);
|
||||
pstart = p + 1;
|
||||
}
|
||||
PRINT_SPACES (fp, desccol);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* end while */
|
||||
free (store);
|
||||
return 0;
|
||||
}
|
||||
#endif /* no scanopt_usage */
|
||||
|
||||
|
||||
static int scanopt_err (s, opt_offset, is_short, err)
|
||||
struct _scanopt_t *s;
|
||||
int opt_offset;
|
||||
int is_short;
|
||||
int err;
|
||||
{
|
||||
const char *optname = "";
|
||||
char optchar[2];
|
||||
const optspec_t *opt = NULL;
|
||||
|
||||
if (opt_offset >= 0)
|
||||
opt = s->options + opt_offset;
|
||||
|
||||
if (!s->no_err_msg) {
|
||||
|
||||
if (s->index > 0 && s->index < s->argc) {
|
||||
if (is_short) {
|
||||
optchar[0] =
|
||||
s->argv[s->index][s->subscript];
|
||||
optchar[1] = '\0';
|
||||
optname = optchar;
|
||||
}
|
||||
else {
|
||||
optname = s->argv[s->index];
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s: ", s->argv[0]);
|
||||
switch (err) {
|
||||
case SCANOPT_ERR_ARG_NOT_ALLOWED:
|
||||
fprintf (stderr,
|
||||
_
|
||||
("option `%s' doesn't allow an argument\n"),
|
||||
optname);
|
||||
break;
|
||||
case SCANOPT_ERR_ARG_NOT_FOUND:
|
||||
fprintf (stderr,
|
||||
_("option `%s' requires an argument\n"),
|
||||
optname);
|
||||
break;
|
||||
case SCANOPT_ERR_OPT_AMBIGUOUS:
|
||||
fprintf (stderr, _("option `%s' is ambiguous\n"),
|
||||
optname);
|
||||
break;
|
||||
case SCANOPT_ERR_OPT_UNRECOGNIZED:
|
||||
fprintf (stderr, _("Unrecognized option `%s'\n"),
|
||||
optname);
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, _("Unknown error=(%d)\n"), err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Internal. Match str against the regex ^--([^=]+)(=(.*))?
|
||||
* return 1 if *looks* like a long option.
|
||||
* 'str' is the only input argument, the rest of the arguments are output only.
|
||||
* optname will point to str + 2
|
||||
*
|
||||
*/
|
||||
static int matchlongopt (str, optname, optlen, arg, arglen)
|
||||
char *str;
|
||||
char **optname;
|
||||
int *optlen;
|
||||
char **arg;
|
||||
int *arglen;
|
||||
{
|
||||
char *p;
|
||||
|
||||
*optname = *arg = (char *) 0;
|
||||
*optlen = *arglen = 0;
|
||||
|
||||
/* Match regex /--./ */
|
||||
p = str;
|
||||
if (p[0] != '-' || p[1] != '-' || !p[2])
|
||||
return 0;
|
||||
|
||||
p += 2;
|
||||
*optname = (char *) p;
|
||||
|
||||
/* find the end of optname */
|
||||
while (*p && *p != '=')
|
||||
++p;
|
||||
|
||||
*optlen = p - *optname;
|
||||
|
||||
if (!*p)
|
||||
/* an option with no '=...' part. */
|
||||
return 1;
|
||||
|
||||
|
||||
/* We saw an '=' char. The rest of p is the arg. */
|
||||
p++;
|
||||
*arg = p;
|
||||
while (*p)
|
||||
++p;
|
||||
*arglen = p - *arg;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Internal. Look up long or short option by name.
|
||||
* Long options must match a non-ambiguous prefix, or exact match.
|
||||
* Short options must be exact.
|
||||
* Return boolean true if found and no error.
|
||||
* Error stored in err_code or zero if no error. */
|
||||
static int find_opt (s, lookup_long, optstart, len, err_code, opt_offset)
|
||||
struct _scanopt_t *s;
|
||||
int lookup_long;
|
||||
char *optstart;
|
||||
int len;
|
||||
int *err_code;
|
||||
int *opt_offset;
|
||||
{
|
||||
int nmatch = 0, lastr_val = 0, i;
|
||||
|
||||
*err_code = 0;
|
||||
*opt_offset = -1;
|
||||
|
||||
if (!optstart)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < s->optc; i++) {
|
||||
char *optname;
|
||||
|
||||
optname =
|
||||
(char *) (s->options[i].opt_fmt +
|
||||
(lookup_long ? 2 : 1));
|
||||
|
||||
if (lookup_long && (s->aux[i].flags & IS_LONG)) {
|
||||
if (len > s->aux[i].namelen)
|
||||
continue;
|
||||
|
||||
if (strncmp (optname, optstart, len) == 0) {
|
||||
nmatch++;
|
||||
*opt_offset = i;
|
||||
|
||||
/* exact match overrides all. */
|
||||
if (len == s->aux[i].namelen) {
|
||||
nmatch = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* ambiguity is ok between aliases. */
|
||||
if (lastr_val
|
||||
&& lastr_val ==
|
||||
s->options[i].r_val) nmatch--;
|
||||
lastr_val = s->options[i].r_val;
|
||||
}
|
||||
}
|
||||
else if (!lookup_long && !(s->aux[i].flags & IS_LONG)) {
|
||||
if (optname[0] == optstart[0]) {
|
||||
nmatch++;
|
||||
*opt_offset = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nmatch == 0) {
|
||||
*err_code = SCANOPT_ERR_OPT_UNRECOGNIZED;
|
||||
*opt_offset = -1;
|
||||
}
|
||||
else if (nmatch > 1) {
|
||||
*err_code = SCANOPT_ERR_OPT_AMBIGUOUS;
|
||||
*opt_offset = -1;
|
||||
}
|
||||
|
||||
return *err_code ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
int scanopt (svoid, arg, optindex)
|
||||
scanopt_t *svoid;
|
||||
char **arg;
|
||||
int *optindex;
|
||||
{
|
||||
char *optname = NULL, *optarg = NULL, *pstart;
|
||||
int namelen = 0, arglen = 0;
|
||||
int errcode = 0, has_next;
|
||||
const optspec_t *optp;
|
||||
struct _scanopt_t *s;
|
||||
struct _aux *auxp;
|
||||
int is_short;
|
||||
int opt_offset = -1;
|
||||
|
||||
s = (struct _scanopt_t *) svoid;
|
||||
|
||||
/* Normalize return-parameters. */
|
||||
SAFE_ASSIGN (arg, NULL);
|
||||
SAFE_ASSIGN (optindex, s->index);
|
||||
|
||||
if (s->index >= s->argc)
|
||||
return 0;
|
||||
|
||||
/* pstart always points to the start of our current scan. */
|
||||
pstart = s->argv[s->index] + s->subscript;
|
||||
if (!pstart)
|
||||
return 0;
|
||||
|
||||
if (s->subscript == 0) {
|
||||
|
||||
/* test for exact match of "--" */
|
||||
if (pstart[0] == '-' && pstart[1] == '-' && !pstart[2]) {
|
||||
SAFE_ASSIGN (optindex, s->index + 1);
|
||||
INC_INDEX (s, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Match an opt. */
|
||||
if (matchlongopt
|
||||
(pstart, &optname, &namelen, &optarg, &arglen)) {
|
||||
|
||||
/* it LOOKS like an opt, but is it one?! */
|
||||
if (!find_opt
|
||||
(s, 1, optname, namelen, &errcode,
|
||||
&opt_offset)) {
|
||||
scanopt_err (s, opt_offset, 0, errcode);
|
||||
return errcode;
|
||||
}
|
||||
/* We handle this below. */
|
||||
is_short = 0;
|
||||
|
||||
/* Check for short opt. */
|
||||
}
|
||||
else if (pstart[0] == '-' && pstart[1]) {
|
||||
/* Pass through to below. */
|
||||
is_short = 1;
|
||||
s->subscript++;
|
||||
pstart++;
|
||||
}
|
||||
|
||||
else {
|
||||
/* It's not an option. We're done. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have to re-check the subscript status because it
|
||||
* may have changed above. */
|
||||
|
||||
if (s->subscript != 0) {
|
||||
|
||||
/* we are somewhere in a run of short opts,
|
||||
* e.g., at the 'z' in `tar -xzf` */
|
||||
|
||||
optname = pstart;
|
||||
namelen = 1;
|
||||
is_short = 1;
|
||||
|
||||
if (!find_opt
|
||||
(s, 0, pstart, namelen, &errcode, &opt_offset)) {
|
||||
return scanopt_err (s, opt_offset, 1, errcode);
|
||||
}
|
||||
|
||||
optarg = pstart + 1;
|
||||
if (!*optarg) {
|
||||
optarg = NULL;
|
||||
arglen = 0;
|
||||
}
|
||||
else
|
||||
arglen = strlen (optarg);
|
||||
}
|
||||
|
||||
/* At this point, we have a long or short option matched at opt_offset into
|
||||
* the s->options array (and corresponding aux array).
|
||||
* A trailing argument is in {optarg,arglen}, if any.
|
||||
*/
|
||||
|
||||
/* Look ahead in argv[] to see if there is something
|
||||
* that we can use as an argument (if needed). */
|
||||
has_next = s->index + 1 < s->argc
|
||||
&& strcmp ("--", s->argv[s->index + 1]) != 0;
|
||||
|
||||
optp = s->options + opt_offset;
|
||||
auxp = s->aux + opt_offset;
|
||||
|
||||
/* case: no args allowed */
|
||||
if (auxp->flags & ARG_NONE) {
|
||||
if (optarg && !is_short) {
|
||||
scanopt_err (s, opt_offset, is_short, errcode =
|
||||
SCANOPT_ERR_ARG_NOT_ALLOWED);
|
||||
INC_INDEX (s, 1);
|
||||
return errcode;
|
||||
}
|
||||
else if (!optarg)
|
||||
INC_INDEX (s, 1);
|
||||
else
|
||||
s->subscript++;
|
||||
return optp->r_val;
|
||||
}
|
||||
|
||||
/* case: required */
|
||||
if (auxp->flags & ARG_REQ) {
|
||||
if (!optarg && !has_next)
|
||||
return scanopt_err (s, opt_offset, is_short,
|
||||
SCANOPT_ERR_ARG_NOT_FOUND);
|
||||
|
||||
if (!optarg) {
|
||||
/* Let the next argv element become the argument. */
|
||||
SAFE_ASSIGN (arg, s->argv[s->index + 1]);
|
||||
INC_INDEX (s, 2);
|
||||
}
|
||||
else {
|
||||
SAFE_ASSIGN (arg, (char *) optarg);
|
||||
INC_INDEX (s, 1);
|
||||
}
|
||||
return optp->r_val;
|
||||
}
|
||||
|
||||
/* case: optional */
|
||||
if (auxp->flags & ARG_OPT) {
|
||||
SAFE_ASSIGN (arg, optarg);
|
||||
INC_INDEX (s, 1);
|
||||
return optp->r_val;
|
||||
}
|
||||
|
||||
|
||||
/* Should not reach here. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int scanopt_destroy (svoid)
|
||||
scanopt_t *svoid;
|
||||
{
|
||||
struct _scanopt_t *s;
|
||||
|
||||
s = (struct _scanopt_t *) svoid;
|
||||
if (s) {
|
||||
if (s->aux)
|
||||
free (s->aux);
|
||||
free (s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */
|
132
contrib/flex/scanopt.h
Normal file
132
contrib/flex/scanopt.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* flex - tool to generate fast lexical analyzers */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#ifndef SCANOPT_H
|
||||
#define SCANOPT_H
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
|
||||
#ifndef NO_SCANOPT_USAGE
|
||||
/* Used by scanopt_usage for pretty-printing. */
|
||||
#ifdef HAVE_NCURSES_H
|
||||
#include <ncurses.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef PROTO
|
||||
#define PROTO(args) args
|
||||
#endif
|
||||
/* Error codes. */ enum scanopt_err_t {
|
||||
SCANOPT_ERR_OPT_UNRECOGNIZED = -1, /* Unrecognized option. */
|
||||
SCANOPT_ERR_OPT_AMBIGUOUS = -2, /* It matched more than one option name. */
|
||||
SCANOPT_ERR_ARG_NOT_FOUND = -3, /* The required arg was not found. */
|
||||
SCANOPT_ERR_ARG_NOT_ALLOWED = -4 /* Option does not take an argument. */
|
||||
};
|
||||
|
||||
|
||||
/* flags passed to scanopt_init */
|
||||
enum scanopt_flag_t {
|
||||
SCANOPT_NO_ERR_MSG = 0x01 /* Suppress printing to stderr. */
|
||||
};
|
||||
|
||||
/* Specification for a single option. */
|
||||
struct optspec_t {
|
||||
const char *opt_fmt; /* e.g., "--foo=FILE", "-f FILE", "-n [NUM]" */
|
||||
int r_val; /* Value to be returned by scanopt_ex(). */
|
||||
const char *desc; /* Brief description of this option, or NULL. */
|
||||
};
|
||||
typedef struct optspec_t optspec_t;
|
||||
|
||||
|
||||
/* Used internally by scanopt() to maintain state. */
|
||||
/* Never modify these value directly. */
|
||||
typedef void *scanopt_t;
|
||||
|
||||
|
||||
/* Initializes scanner and checks option list for errors.
|
||||
* Parameters:
|
||||
* options - Array of options.
|
||||
* argc - Same as passed to main().
|
||||
* argv - Same as passed to main(). First element is skipped.
|
||||
* flags - Control behavior.
|
||||
* Return: A malloc'd pointer .
|
||||
*/
|
||||
scanopt_t *scanopt_init PROTO ((const optspec_t * options,
|
||||
int argc, char **argv, int flags));
|
||||
|
||||
/* Frees memory used by scanner.
|
||||
* Always returns 0. */
|
||||
int scanopt_destroy PROTO ((scanopt_t * scanner));
|
||||
|
||||
#ifndef NO_SCANOPT_USAGE
|
||||
/* Prints a usage message based on contents of optlist.
|
||||
* Parameters:
|
||||
* scanner - The scanner, already initialized with scanopt_init().
|
||||
* fp - The file stream to write to.
|
||||
* usage - Text to be prepended to option list. May be NULL.
|
||||
* Return: Always returns 0 (zero).
|
||||
*/
|
||||
int scanopt_usage
|
||||
PROTO (
|
||||
(scanopt_t * scanner, FILE * fp,
|
||||
const char *usage));
|
||||
#endif
|
||||
|
||||
/* Scans command-line options in argv[].
|
||||
* Parameters:
|
||||
* scanner - The scanner, already initialized with scanopt_init().
|
||||
* optarg - Return argument, may be NULL.
|
||||
* On success, it points to start of an argument.
|
||||
* optindex - Return argument, may be NULL.
|
||||
* On success or failure, it is the index of this option.
|
||||
* If return is zero, then optindex is the NEXT valid option index.
|
||||
*
|
||||
* Return: > 0 on success. Return value is from optspec_t->rval.
|
||||
* == 0 if at end of options.
|
||||
* < 0 on error (return value is an error code).
|
||||
*
|
||||
*/
|
||||
int scanopt
|
||||
PROTO (
|
||||
(scanopt_t * scanner, char **optarg,
|
||||
int *optindex));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */
|
272
contrib/flex/sym.c
Normal file
272
contrib/flex/sym.c
Normal file
@ -0,0 +1,272 @@
|
||||
/* sym - symbol table routines */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
/* Variables for symbol tables:
|
||||
* sctbl - start-condition symbol table
|
||||
* ndtbl - name-definition symbol table
|
||||
* ccltab - character class text symbol table
|
||||
*/
|
||||
|
||||
struct hash_entry {
|
||||
struct hash_entry *prev, *next;
|
||||
char *name;
|
||||
char *str_val;
|
||||
int int_val;
|
||||
};
|
||||
|
||||
typedef struct hash_entry **hash_table;
|
||||
|
||||
#define NAME_TABLE_HASH_SIZE 101
|
||||
#define START_COND_HASH_SIZE 101
|
||||
#define CCL_HASH_SIZE 101
|
||||
|
||||
static struct hash_entry *ndtbl[NAME_TABLE_HASH_SIZE];
|
||||
static struct hash_entry *sctbl[START_COND_HASH_SIZE];
|
||||
static struct hash_entry *ccltab[CCL_HASH_SIZE];
|
||||
|
||||
|
||||
/* declare functions that have forward references */
|
||||
|
||||
static int addsym PROTO ((register char[], char *, int, hash_table, int));
|
||||
static struct hash_entry *findsym PROTO ((register const char *sym,
|
||||
hash_table table,
|
||||
|
||||
int table_size));
|
||||
static int hashfunct PROTO ((register const char *, int));
|
||||
|
||||
|
||||
/* addsym - add symbol and definitions to symbol table
|
||||
*
|
||||
* -1 is returned if the symbol already exists, and the change not made.
|
||||
*/
|
||||
|
||||
static int addsym (sym, str_def, int_def, table, table_size)
|
||||
register char sym[];
|
||||
char *str_def;
|
||||
int int_def;
|
||||
hash_table table;
|
||||
int table_size;
|
||||
{
|
||||
int hash_val = hashfunct (sym, table_size);
|
||||
register struct hash_entry *sym_entry = table[hash_val];
|
||||
register struct hash_entry *new_entry;
|
||||
register struct hash_entry *successor;
|
||||
|
||||
while (sym_entry) {
|
||||
if (!strcmp (sym, sym_entry->name)) { /* entry already exists */
|
||||
return -1;
|
||||
}
|
||||
|
||||
sym_entry = sym_entry->next;
|
||||
}
|
||||
|
||||
/* create new entry */
|
||||
new_entry = (struct hash_entry *)
|
||||
flex_alloc (sizeof (struct hash_entry));
|
||||
|
||||
if (new_entry == NULL)
|
||||
flexfatal (_("symbol table memory allocation failed"));
|
||||
|
||||
if ((successor = table[hash_val]) != 0) {
|
||||
new_entry->next = successor;
|
||||
successor->prev = new_entry;
|
||||
}
|
||||
else
|
||||
new_entry->next = NULL;
|
||||
|
||||
new_entry->prev = NULL;
|
||||
new_entry->name = sym;
|
||||
new_entry->str_val = str_def;
|
||||
new_entry->int_val = int_def;
|
||||
|
||||
table[hash_val] = new_entry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* cclinstal - save the text of a character class */
|
||||
|
||||
void cclinstal (ccltxt, cclnum)
|
||||
Char ccltxt[];
|
||||
int cclnum;
|
||||
{
|
||||
/* We don't bother checking the return status because we are not
|
||||
* called unless the symbol is new.
|
||||
*/
|
||||
|
||||
(void) addsym ((char *) copy_unsigned_string (ccltxt),
|
||||
(char *) 0, cclnum, ccltab, CCL_HASH_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/* ccllookup - lookup the number associated with character class text
|
||||
*
|
||||
* Returns 0 if there's no CCL associated with the text.
|
||||
*/
|
||||
|
||||
int ccllookup (ccltxt)
|
||||
Char ccltxt[];
|
||||
{
|
||||
return findsym ((char *) ccltxt, ccltab, CCL_HASH_SIZE)->int_val;
|
||||
}
|
||||
|
||||
|
||||
/* findsym - find symbol in symbol table */
|
||||
|
||||
static struct hash_entry *findsym (sym, table, table_size)
|
||||
register const char *sym;
|
||||
hash_table table;
|
||||
int table_size;
|
||||
{
|
||||
static struct hash_entry empty_entry = {
|
||||
(struct hash_entry *) 0, (struct hash_entry *) 0,
|
||||
(char *) 0, (char *) 0, 0,
|
||||
};
|
||||
register struct hash_entry *sym_entry =
|
||||
|
||||
table[hashfunct (sym, table_size)];
|
||||
|
||||
while (sym_entry) {
|
||||
if (!strcmp (sym, sym_entry->name))
|
||||
return sym_entry;
|
||||
sym_entry = sym_entry->next;
|
||||
}
|
||||
|
||||
return &empty_entry;
|
||||
}
|
||||
|
||||
/* hashfunct - compute the hash value for "str" and hash size "hash_size" */
|
||||
|
||||
static int hashfunct (str, hash_size)
|
||||
register const char *str;
|
||||
int hash_size;
|
||||
{
|
||||
register int hashval;
|
||||
register int locstr;
|
||||
|
||||
hashval = 0;
|
||||
locstr = 0;
|
||||
|
||||
while (str[locstr]) {
|
||||
hashval = (hashval << 1) + (unsigned char) str[locstr++];
|
||||
hashval %= hash_size;
|
||||
}
|
||||
|
||||
return hashval;
|
||||
}
|
||||
|
||||
|
||||
/* ndinstal - install a name definition */
|
||||
|
||||
void ndinstal (name, definition)
|
||||
const char *name;
|
||||
Char definition[];
|
||||
{
|
||||
|
||||
if (addsym (copy_string (name),
|
||||
(char *) copy_unsigned_string (definition), 0,
|
||||
ndtbl, NAME_TABLE_HASH_SIZE))
|
||||
synerr (_("name defined twice"));
|
||||
}
|
||||
|
||||
|
||||
/* ndlookup - lookup a name definition
|
||||
*
|
||||
* Returns a nil pointer if the name definition does not exist.
|
||||
*/
|
||||
|
||||
Char *ndlookup (nd)
|
||||
const char *nd;
|
||||
{
|
||||
return (Char *) findsym (nd, ndtbl, NAME_TABLE_HASH_SIZE)->str_val;
|
||||
}
|
||||
|
||||
|
||||
/* scextend - increase the maximum number of start conditions */
|
||||
|
||||
void scextend ()
|
||||
{
|
||||
current_max_scs += MAX_SCS_INCREMENT;
|
||||
|
||||
++num_reallocs;
|
||||
|
||||
scset = reallocate_integer_array (scset, current_max_scs);
|
||||
scbol = reallocate_integer_array (scbol, current_max_scs);
|
||||
scxclu = reallocate_integer_array (scxclu, current_max_scs);
|
||||
sceof = reallocate_integer_array (sceof, current_max_scs);
|
||||
scname = reallocate_char_ptr_array (scname, current_max_scs);
|
||||
}
|
||||
|
||||
|
||||
/* scinstal - make a start condition
|
||||
*
|
||||
* NOTE
|
||||
* The start condition is "exclusive" if xcluflg is true.
|
||||
*/
|
||||
|
||||
void scinstal (str, xcluflg)
|
||||
const char *str;
|
||||
int xcluflg;
|
||||
{
|
||||
|
||||
if (++lastsc >= current_max_scs)
|
||||
scextend ();
|
||||
|
||||
scname[lastsc] = copy_string (str);
|
||||
|
||||
if (addsym (scname[lastsc], (char *) 0, lastsc,
|
||||
sctbl, START_COND_HASH_SIZE))
|
||||
format_pinpoint_message (_
|
||||
("start condition %s declared twice"),
|
||||
str);
|
||||
|
||||
scset[lastsc] = mkstate (SYM_EPSILON);
|
||||
scbol[lastsc] = mkstate (SYM_EPSILON);
|
||||
scxclu[lastsc] = xcluflg;
|
||||
sceof[lastsc] = false;
|
||||
}
|
||||
|
||||
|
||||
/* sclookup - lookup the number associated with a start condition
|
||||
*
|
||||
* Returns 0 if no such start condition.
|
||||
*/
|
||||
|
||||
int sclookup (str)
|
||||
const char *str;
|
||||
{
|
||||
return findsym (str, sctbl, START_COND_HASH_SIZE)->int_val;
|
||||
}
|
502
contrib/flex/tables.c
Normal file
502
contrib/flex/tables.c
Normal file
@ -0,0 +1,502 @@
|
||||
/* tables.c - tables serialization code
|
||||
*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Vern Paxson.
|
||||
*
|
||||
* The United States Government has rights in this work pursuant
|
||||
* to contract no. DE-AC03-76SF00098 between the United States
|
||||
* Department of Energy and the University of California.
|
||||
*
|
||||
* This file is part of flex.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
|
||||
|
||||
#include "flexdef.h"
|
||||
#include "tables.h"
|
||||
|
||||
/** Convert size_t to t_flag.
|
||||
* @param n in {1,2,4}
|
||||
* @return YYTD_DATA*.
|
||||
*/
|
||||
#define BYTES2TFLAG(n)\
|
||||
(((n) == sizeof(flex_int8_t))\
|
||||
? YYTD_DATA8\
|
||||
:(((n)== sizeof(flex_int16_t))\
|
||||
? YYTD_DATA16\
|
||||
: YYTD_DATA32))
|
||||
|
||||
/** Clear YYTD_DATA* bit flags
|
||||
* @return the flag with the YYTD_DATA* bits cleared
|
||||
*/
|
||||
#define TFLAGS_CLRDATA(flg) ((flg) & ~(YYTD_DATA8 | YYTD_DATA16 | YYTD_DATA32))
|
||||
|
||||
int yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v);
|
||||
int yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v);
|
||||
int yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v);
|
||||
int yytbl_writen (struct yytbl_writer *wr, void *v, flex_int32_t len);
|
||||
static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i);
|
||||
/* XXX Not used
|
||||
static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
|
||||
int j, int k);
|
||||
*/
|
||||
|
||||
|
||||
/** Initialize the table writer.
|
||||
* @param wr an uninitialized writer
|
||||
* @param the output file
|
||||
* @return 0 on success
|
||||
*/
|
||||
int yytbl_writer_init (struct yytbl_writer *wr, FILE * out)
|
||||
{
|
||||
wr->out = out;
|
||||
wr->total_written = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Initialize a table header.
|
||||
* @param th The uninitialized structure
|
||||
* @param version_str the version string
|
||||
* @param name the name of this table set
|
||||
*/
|
||||
int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str,
|
||||
const char *name)
|
||||
{
|
||||
memset (th, 0, sizeof (struct yytbl_hdr));
|
||||
|
||||
th->th_magic = YYTBL_MAGIC;
|
||||
th->th_hsize = 14 + strlen (version_str) + 1 + strlen (name) + 1;
|
||||
th->th_hsize += yypad64 (th->th_hsize);
|
||||
th->th_ssize = 0; // Not known at this point.
|
||||
th->th_flags = 0;
|
||||
th->th_version = copy_string (version_str);
|
||||
th->th_name = copy_string (name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Allocate and initialize a table data structure.
|
||||
* @param tbl a pointer to an uninitialized table
|
||||
* @param id the table identifier
|
||||
* @return 0 on success
|
||||
*/
|
||||
int yytbl_data_init (struct yytbl_data *td, enum yytbl_id id)
|
||||
{
|
||||
|
||||
memset (td, 0, sizeof (struct yytbl_data));
|
||||
td->td_id = id;
|
||||
td->td_flags = YYTD_DATA32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Clean up table and data array.
|
||||
* @param td will be destroyed
|
||||
* @return 0 on success
|
||||
*/
|
||||
int yytbl_data_destroy (struct yytbl_data *td)
|
||||
{
|
||||
if (td->td_data)
|
||||
free (td->td_data);
|
||||
td->td_data = 0;
|
||||
free (td);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Write enough padding to bring the file pointer to a 64-bit boundary. */
|
||||
static int yytbl_write_pad64 (struct yytbl_writer *wr)
|
||||
{
|
||||
int pad, bwritten = 0;
|
||||
|
||||
pad = yypad64 (wr->total_written);
|
||||
while (pad-- > 0)
|
||||
if (yytbl_write8 (wr, 0) < 0)
|
||||
return -1;
|
||||
else
|
||||
bwritten++;
|
||||
return bwritten;
|
||||
}
|
||||
|
||||
/** write the header.
|
||||
* @param out the output stream
|
||||
* @param th table header to be written
|
||||
* @return -1 on error, or bytes written on success.
|
||||
*/
|
||||
int yytbl_hdr_fwrite (struct yytbl_writer *wr, const struct yytbl_hdr *th)
|
||||
{
|
||||
int sz, rv;
|
||||
int bwritten = 0;
|
||||
|
||||
if (yytbl_write32 (wr, th->th_magic) < 0
|
||||
|| yytbl_write32 (wr, th->th_hsize) < 0)
|
||||
flex_die (_("th_magic|th_hsize write32 failed"));
|
||||
bwritten += 8;
|
||||
|
||||
if (fgetpos (wr->out, &(wr->th_ssize_pos)) != 0)
|
||||
flex_die (_("fgetpos failed"));
|
||||
|
||||
if (yytbl_write32 (wr, th->th_ssize) < 0
|
||||
|| yytbl_write16 (wr, th->th_flags) < 0)
|
||||
flex_die (_("th_ssize|th_flags write failed"));
|
||||
bwritten += 6;
|
||||
|
||||
sz = strlen (th->th_version) + 1;
|
||||
if ((rv = yytbl_writen (wr, th->th_version, sz)) != sz)
|
||||
flex_die (_("th_version writen failed"));
|
||||
bwritten += rv;
|
||||
|
||||
sz = strlen (th->th_name) + 1;
|
||||
if ((rv = yytbl_writen (wr, th->th_name, sz)) != sz)
|
||||
flex_die (_("th_name writen failed"));
|
||||
bwritten += rv;
|
||||
|
||||
/* add padding */
|
||||
if ((rv = yytbl_write_pad64 (wr)) < 0)
|
||||
flex_die (_("pad64 failed"));
|
||||
bwritten += rv;
|
||||
|
||||
/* Sanity check */
|
||||
if (bwritten != (int) th->th_hsize)
|
||||
flex_die (_("pad64 failed"));
|
||||
|
||||
return bwritten;
|
||||
}
|
||||
|
||||
|
||||
/** Write this table.
|
||||
* @param out the file writer
|
||||
* @param td table data to be written
|
||||
* @return -1 on error, or bytes written on success.
|
||||
*/
|
||||
int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td)
|
||||
{
|
||||
int rv;
|
||||
flex_int32_t bwritten = 0;
|
||||
flex_int32_t i, total_len;
|
||||
fpos_t pos;
|
||||
|
||||
if ((rv = yytbl_write16 (wr, td->td_id)) < 0)
|
||||
return -1;
|
||||
bwritten += rv;
|
||||
|
||||
if ((rv = yytbl_write16 (wr, td->td_flags)) < 0)
|
||||
return -1;
|
||||
bwritten += rv;
|
||||
|
||||
if ((rv = yytbl_write32 (wr, td->td_hilen)) < 0)
|
||||
return -1;
|
||||
bwritten += rv;
|
||||
|
||||
if ((rv = yytbl_write32 (wr, td->td_lolen)) < 0)
|
||||
return -1;
|
||||
bwritten += rv;
|
||||
|
||||
total_len = yytbl_calc_total_len (td);
|
||||
for (i = 0; i < total_len; i++) {
|
||||
switch (YYTDFLAGS2BYTES (td->td_flags)) {
|
||||
case sizeof (flex_int8_t):
|
||||
rv = yytbl_write8 (wr, yytbl_data_geti (td, i));
|
||||
break;
|
||||
case sizeof (flex_int16_t):
|
||||
rv = yytbl_write16 (wr, yytbl_data_geti (td, i));
|
||||
break;
|
||||
case sizeof (flex_int32_t):
|
||||
rv = yytbl_write32 (wr, yytbl_data_geti (td, i));
|
||||
break;
|
||||
default:
|
||||
flex_die (_("invalid td_flags detected"));
|
||||
}
|
||||
if (rv < 0) {
|
||||
flex_die (_("error while writing tables"));
|
||||
return -1;
|
||||
}
|
||||
bwritten += rv;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if (bwritten != (int) (12 + total_len * YYTDFLAGS2BYTES (td->td_flags))) {
|
||||
flex_die (_("insanity detected"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* add padding */
|
||||
if ((rv = yytbl_write_pad64 (wr)) < 0) {
|
||||
flex_die (_("pad64 failed"));
|
||||
return -1;
|
||||
}
|
||||
bwritten += rv;
|
||||
|
||||
/* Now go back and update the th_hsize member */
|
||||
if (fgetpos (wr->out, &pos) != 0
|
||||
|| fsetpos (wr->out, &(wr->th_ssize_pos)) != 0
|
||||
|| yytbl_write32 (wr, wr->total_written) < 0
|
||||
|| fsetpos (wr->out, &pos)) {
|
||||
flex_die (_("get|set|fwrite32 failed"));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
/* Don't count the int we just wrote. */
|
||||
wr->total_written -= sizeof (flex_int32_t);
|
||||
return bwritten;
|
||||
}
|
||||
|
||||
/** Write n bytes.
|
||||
* @param wr the table writer
|
||||
* @param v data to be written
|
||||
* @param len number of bytes
|
||||
* @return -1 on error. number of bytes written on success.
|
||||
*/
|
||||
int yytbl_writen (struct yytbl_writer *wr, void *v, flex_int32_t len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = fwrite (v, 1, len, wr->out);
|
||||
if (rv != len)
|
||||
return -1;
|
||||
wr->total_written += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/** Write four bytes in network byte order
|
||||
* @param wr the table writer
|
||||
* @param v a dword in host byte order
|
||||
* @return -1 on error. number of bytes written on success.
|
||||
*/
|
||||
int yytbl_write32 (struct yytbl_writer *wr, flex_uint32_t v)
|
||||
{
|
||||
flex_uint32_t vnet;
|
||||
size_t bytes, rv;
|
||||
|
||||
vnet = htonl (v);
|
||||
bytes = sizeof (flex_uint32_t);
|
||||
rv = fwrite (&vnet, bytes, 1, wr->out);
|
||||
if (rv != 1)
|
||||
return -1;
|
||||
wr->total_written += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/** Write two bytes in network byte order.
|
||||
* @param wr the table writer
|
||||
* @param v a word in host byte order
|
||||
* @return -1 on error. number of bytes written on success.
|
||||
*/
|
||||
int yytbl_write16 (struct yytbl_writer *wr, flex_uint16_t v)
|
||||
{
|
||||
flex_uint16_t vnet;
|
||||
size_t bytes, rv;
|
||||
|
||||
vnet = htons (v);
|
||||
bytes = sizeof (flex_uint16_t);
|
||||
rv = fwrite (&vnet, bytes, 1, wr->out);
|
||||
if (rv != 1)
|
||||
return -1;
|
||||
wr->total_written += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/** Write a byte.
|
||||
* @param wr the table writer
|
||||
* @param v the value to be written
|
||||
* @return -1 on error. number of bytes written on success.
|
||||
*/
|
||||
int yytbl_write8 (struct yytbl_writer *wr, flex_uint8_t v)
|
||||
{
|
||||
size_t bytes, rv;
|
||||
|
||||
bytes = sizeof (flex_uint8_t);
|
||||
rv = fwrite (&v, bytes, 1, wr->out);
|
||||
if (rv != 1)
|
||||
return -1;
|
||||
wr->total_written += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/* XXX Not Used */
|
||||
#if 0
|
||||
/** Extract data element [i][j] from array data tables.
|
||||
* @param tbl data table
|
||||
* @param i index into higher dimension array. i should be zero for one-dimensional arrays.
|
||||
* @param j index into lower dimension array.
|
||||
* @param k index into struct, must be 0 or 1. Only valid for YYTD_ID_TRANSITION table
|
||||
* @return data[i][j + k]
|
||||
*/
|
||||
static flex_int32_t yytbl_data_getijk (const struct yytbl_data *tbl, int i,
|
||||
int j, int k)
|
||||
{
|
||||
flex_int32_t lo;
|
||||
|
||||
k %= 2;
|
||||
lo = tbl->td_lolen;
|
||||
|
||||
switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
|
||||
case sizeof (flex_int8_t):
|
||||
return ((flex_int8_t *) (tbl->td_data))[(i * lo + j) * (k + 1) +
|
||||
k];
|
||||
case sizeof (flex_int16_t):
|
||||
return ((flex_int16_t *) (tbl->td_data))[(i * lo + j) * (k +
|
||||
1) +
|
||||
k];
|
||||
case sizeof (flex_int32_t):
|
||||
return ((flex_int32_t *) (tbl->td_data))[(i * lo + j) * (k +
|
||||
1) +
|
||||
k];
|
||||
default:
|
||||
flex_die (_("invalid td_flags detected"));
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* Not used */
|
||||
|
||||
/** Extract data element [i] from array data tables treated as a single flat array of integers.
|
||||
* Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
|
||||
* of structs.
|
||||
* @param tbl data table
|
||||
* @param i index into array.
|
||||
* @return data[i]
|
||||
*/
|
||||
static flex_int32_t yytbl_data_geti (const struct yytbl_data *tbl, int i)
|
||||
{
|
||||
|
||||
switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
|
||||
case sizeof (flex_int8_t):
|
||||
return ((flex_int8_t *) (tbl->td_data))[i];
|
||||
case sizeof (flex_int16_t):
|
||||
return ((flex_int16_t *) (tbl->td_data))[i];
|
||||
case sizeof (flex_int32_t):
|
||||
return ((flex_int32_t *) (tbl->td_data))[i];
|
||||
default:
|
||||
flex_die (_("invalid td_flags detected"));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Set data element [i] in array data tables treated as a single flat array of integers.
|
||||
* Be careful for 2-dimensional arrays or for YYTD_ID_TRANSITION, which is an array
|
||||
* of structs.
|
||||
* @param tbl data table
|
||||
* @param i index into array.
|
||||
* @param newval new value for data[i]
|
||||
*/
|
||||
static void yytbl_data_seti (const struct yytbl_data *tbl, int i,
|
||||
flex_int32_t newval)
|
||||
{
|
||||
|
||||
switch (YYTDFLAGS2BYTES (tbl->td_flags)) {
|
||||
case sizeof (flex_int8_t):
|
||||
((flex_int8_t *) (tbl->td_data))[i] = (flex_int8_t) newval;
|
||||
break;
|
||||
case sizeof (flex_int16_t):
|
||||
((flex_int16_t *) (tbl->td_data))[i] = (flex_int16_t) newval;
|
||||
break;
|
||||
case sizeof (flex_int32_t):
|
||||
((flex_int32_t *) (tbl->td_data))[i] = (flex_int32_t) newval;
|
||||
break;
|
||||
default:
|
||||
flex_die (_("invalid td_flags detected"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Calculate the number of bytes needed to hold the largest
|
||||
* absolute value in this data array.
|
||||
* @param tbl the data table
|
||||
* @return sizeof(n) where n in {flex_int8_t, flex_int16_t, flex_int32_t}
|
||||
*/
|
||||
static size_t min_int_size (struct yytbl_data *tbl)
|
||||
{
|
||||
flex_uint32_t i, total_len;
|
||||
flex_int32_t max = 0;
|
||||
|
||||
total_len = yytbl_calc_total_len (tbl);
|
||||
|
||||
for (i = 0; i < total_len; i++) {
|
||||
flex_int32_t n;
|
||||
|
||||
n = abs (yytbl_data_geti (tbl, i));
|
||||
|
||||
if (n > max)
|
||||
max = n;
|
||||
}
|
||||
|
||||
if (max <= INT8_MAX)
|
||||
return sizeof (flex_int8_t);
|
||||
else if (max <= INT16_MAX)
|
||||
return sizeof (flex_int16_t);
|
||||
else
|
||||
return sizeof (flex_int32_t);
|
||||
}
|
||||
|
||||
/** Transform data to smallest possible of (int32, int16, int8).
|
||||
* For example, we may have generated an int32 array due to user options
|
||||
* (e.g., %option align), but if the maximum value in that array
|
||||
* is 80 (for example), then we can serialize it with only 1 byte per int.
|
||||
* This is NOT the same as compressed DFA tables. We're just trying
|
||||
* to save storage space here.
|
||||
*
|
||||
* @param tbl the table to be compressed
|
||||
*/
|
||||
void yytbl_data_compress (struct yytbl_data *tbl)
|
||||
{
|
||||
flex_int32_t i, newsz, total_len;
|
||||
struct yytbl_data newtbl;
|
||||
|
||||
yytbl_data_init (&newtbl, tbl->td_id);
|
||||
newtbl.td_hilen = tbl->td_hilen;
|
||||
newtbl.td_lolen = tbl->td_lolen;
|
||||
newtbl.td_flags = tbl->td_flags;
|
||||
|
||||
newsz = min_int_size (tbl);
|
||||
|
||||
|
||||
if (newsz == (int) YYTDFLAGS2BYTES (tbl->td_flags))
|
||||
/* No change in this table needed. */
|
||||
return;
|
||||
|
||||
if (newsz > (int) YYTDFLAGS2BYTES (tbl->td_flags)) {
|
||||
flex_die (_("detected negative compression"));
|
||||
return;
|
||||
}
|
||||
|
||||
total_len = yytbl_calc_total_len (tbl);
|
||||
newtbl.td_data = calloc (total_len, newsz);
|
||||
newtbl.td_flags =
|
||||
TFLAGS_CLRDATA (newtbl.td_flags) | BYTES2TFLAG (newsz);
|
||||
|
||||
for (i = 0; i < total_len; i++) {
|
||||
flex_int32_t g;
|
||||
|
||||
g = yytbl_data_geti (tbl, i);
|
||||
yytbl_data_seti (&newtbl, i, g);
|
||||
}
|
||||
|
||||
|
||||
/* Now copy over the old table */
|
||||
free (tbl->td_data);
|
||||
*tbl = newtbl;
|
||||
}
|
||||
|
||||
/* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */
|
85
contrib/flex/tables.h
Normal file
85
contrib/flex/tables.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* tables.h - tables serialization code
|
||||
*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Vern Paxson.
|
||||
*
|
||||
* The United States Government has rights in this work pursuant
|
||||
* to contract no. DE-AC03-76SF00098 between the United States
|
||||
* Department of Energy and the University of California.
|
||||
*
|
||||
* This file is part of flex.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef TABLES_H
|
||||
#define TABLES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
/* Tables serialization API declarations. */
|
||||
#include "tables_shared.h"
|
||||
struct yytbl_writer {
|
||||
FILE *out;
|
||||
flex_uint32_t total_written;
|
||||
/**< bytes written so far */
|
||||
fpos_t th_ssize_pos;
|
||||
/**< position of th_ssize */
|
||||
};
|
||||
|
||||
/* These are used by main.c, gen.c, etc.
|
||||
* tablesext - if true, create external tables
|
||||
* tablesfilename - filename for external tables
|
||||
* tablesname - name that goes in serialized data, e.g., "yytables"
|
||||
* tableswr - writer for external tables
|
||||
* tablesverify - true if tables-verify option specified
|
||||
* gentables - true if we should spit out the normal C tables
|
||||
*/
|
||||
extern bool tablesext, tablesverify,gentables;
|
||||
extern char *tablesfilename, *tablesname;
|
||||
extern struct yytbl_writer tableswr;
|
||||
|
||||
int yytbl_writer_init (struct yytbl_writer *, FILE *);
|
||||
int yytbl_hdr_init (struct yytbl_hdr *th, const char *version_str,
|
||||
const char *name);
|
||||
int yytbl_data_init (struct yytbl_data *tbl, enum yytbl_id id);
|
||||
int yytbl_data_destroy (struct yytbl_data *td);
|
||||
int yytbl_hdr_fwrite (struct yytbl_writer *wr,
|
||||
const struct yytbl_hdr *th);
|
||||
int yytbl_data_fwrite (struct yytbl_writer *wr, struct yytbl_data *td);
|
||||
void yytbl_data_compress (struct yytbl_data *tbl);
|
||||
struct yytbl_data *mkftbl (void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* vim:set expandtab cindent tabstop=4 softtabstop=4 shiftwidth=4 textwidth=0: */
|
70
contrib/flex/tables_shared.c
Normal file
70
contrib/flex/tables_shared.c
Normal file
@ -0,0 +1,70 @@
|
||||
#ifdef FLEX_SCANNER
|
||||
/*
|
||||
dnl tables_shared.c - tables serialization code
|
||||
dnl
|
||||
dnl Copyright (c) 1990 The Regents of the University of California.
|
||||
dnl All rights reserved.
|
||||
dnl
|
||||
dnl This code is derived from software contributed to Berkeley by
|
||||
dnl Vern Paxson.
|
||||
dnl
|
||||
dnl The United States Government has rights in this work pursuant
|
||||
dnl to contract no. DE-AC03-76SF00098 between the United States
|
||||
dnl Department of Energy and the University of California.
|
||||
dnl
|
||||
dnl This file is part of flex.
|
||||
dnl
|
||||
dnl Redistribution and use in source and binary forms, with or without
|
||||
dnl modification, are permitted provided that the following conditions
|
||||
dnl are met:
|
||||
dnl
|
||||
dnl 1. Redistributions of source code must retain the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer.
|
||||
dnl 2. Redistributions in binary form must reproduce the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer in the
|
||||
dnl documentation and/or other materials provided with the distribution.
|
||||
dnl
|
||||
dnl Neither the name of the University nor the names of its contributors
|
||||
dnl may be used to endorse or promote products derived from this software
|
||||
dnl without specific prior written permission.
|
||||
dnl
|
||||
dnl THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
dnl IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
dnl PURPOSE.
|
||||
dnl
|
||||
*/
|
||||
|
||||
/* This file is meant to be included in both the skeleton and the actual
|
||||
* flex code (hence the name "_shared").
|
||||
*/
|
||||
#ifndef yyskel_static
|
||||
#define yyskel_static static
|
||||
#endif
|
||||
#else
|
||||
#include "flexdef.h"
|
||||
#include "tables.h"
|
||||
#ifndef yyskel_static
|
||||
#define yyskel_static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/** Get the number of integers in this table. This is NOT the
|
||||
* same thing as the number of elements.
|
||||
* @param td the table
|
||||
* @return the number of integers in the table
|
||||
*/
|
||||
yyskel_static flex_int32_t yytbl_calc_total_len (const struct yytbl_data *tbl)
|
||||
{
|
||||
flex_int32_t n;
|
||||
|
||||
/* total number of ints */
|
||||
n = tbl->td_lolen;
|
||||
if (tbl->td_hilen > 0)
|
||||
n *= tbl->td_hilen;
|
||||
|
||||
if (tbl->td_id == YYTD_ID_TRANSITION)
|
||||
n *= 2;
|
||||
return n;
|
||||
}
|
144
contrib/flex/tables_shared.h
Normal file
144
contrib/flex/tables_shared.h
Normal file
@ -0,0 +1,144 @@
|
||||
#ifdef FLEX_SCANNER
|
||||
/*
|
||||
dnl tables_shared.h - tables serialization header
|
||||
dnl
|
||||
dnl Copyright (c) 1990 The Regents of the University of California.
|
||||
dnl All rights reserved.
|
||||
dnl
|
||||
dnl This code is derived from software contributed to Berkeley by
|
||||
dnl Vern Paxson.
|
||||
dnl
|
||||
dnl The United States Government has rights in this work pursuant
|
||||
dnl to contract no. DE-AC03-76SF00098 between the United States
|
||||
dnl Department of Energy and the University of California.
|
||||
dnl
|
||||
dnl This file is part of flex.
|
||||
dnl
|
||||
dnl Redistribution and use in source and binary forms, with or without
|
||||
dnl modification, are permitted provided that the following conditions
|
||||
dnl are met:
|
||||
dnl
|
||||
dnl 1. Redistributions of source code must retain the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer.
|
||||
dnl 2. Redistributions in binary form must reproduce the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer in the
|
||||
dnl documentation and/or other materials provided with the distribution.
|
||||
dnl
|
||||
dnl Neither the name of the University nor the names of its contributors
|
||||
dnl may be used to endorse or promote products derived from this software
|
||||
dnl without specific prior written permission.
|
||||
dnl
|
||||
dnl THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
dnl IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
dnl PURPOSE.
|
||||
|
||||
dnl
|
||||
dnl This file is meant to be included in both the skeleton and the actual
|
||||
dnl flex code (hence the name "_shared").
|
||||
*/
|
||||
#ifndef yyskel_static
|
||||
#define yyskel_static static
|
||||
#endif
|
||||
#else
|
||||
#ifndef yyskel_static
|
||||
#define yyskel_static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Structures and prototypes for serializing flex tables. The
|
||||
* binary format is documented in the manual.
|
||||
*
|
||||
* Design considerations:
|
||||
*
|
||||
* - The format allows many tables per file.
|
||||
* - The tables can be streamed.
|
||||
* - All data is stored in network byte order.
|
||||
* - We do not hinder future unicode support.
|
||||
* - We can lookup tables by name.
|
||||
*/
|
||||
|
||||
/** Magic number for serialized format. */
|
||||
#ifndef YYTBL_MAGIC
|
||||
#define YYTBL_MAGIC 0xF13C57B1
|
||||
#endif
|
||||
|
||||
/** Calculate (0-7) = number bytes needed to pad n to next 64-bit boundary. */
|
||||
#ifndef yypad64
|
||||
#define yypad64(n) ((8-((n)%8))%8)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef YYTABLES_TYPES
|
||||
#define YYTABLES_TYPES
|
||||
/** Possible values for td_id field. Each one corresponds to a
|
||||
* scanner table of the same name.
|
||||
*/
|
||||
enum yytbl_id {
|
||||
YYTD_ID_ACCEPT = 0x01, /**< 1-dim ints */
|
||||
YYTD_ID_BASE = 0x02, /**< 1-dim ints */
|
||||
YYTD_ID_CHK = 0x03, /**< 1-dim ints */
|
||||
YYTD_ID_DEF = 0x04, /**< 1-dim ints */
|
||||
YYTD_ID_EC = 0x05, /**< 1-dim ints */
|
||||
YYTD_ID_META = 0x06, /**< 1-dim ints */
|
||||
YYTD_ID_NUL_TRANS = 0x07, /**< 1-dim ints, maybe indices */
|
||||
YYTD_ID_NXT = 0x08, /**< may be 2 dimensional ints */
|
||||
YYTD_ID_RULE_CAN_MATCH_EOL = 0x09, /**< 1-dim ints */
|
||||
YYTD_ID_START_STATE_LIST = 0x0A, /**< 1-dim indices into trans tbl */
|
||||
YYTD_ID_TRANSITION = 0x0B, /**< structs */
|
||||
YYTD_ID_ACCLIST = 0x0C /**< 1-dim ints */
|
||||
};
|
||||
|
||||
/** bit flags for t_flags field of struct yytbl_data */
|
||||
enum yytbl_flags {
|
||||
/* These first three are mutually exclusive */
|
||||
YYTD_DATA8 = 0x01, /**< data is an array of type flex_int8_t */
|
||||
YYTD_DATA16 = 0x02, /**< data is an array of type flex_int16_t */
|
||||
YYTD_DATA32 = 0x04, /**< data is an array of type flex_int32_t */
|
||||
|
||||
/* These two are mutually exclusive. */
|
||||
YYTD_PTRANS = 0x08, /**< data is a list of indexes of entries
|
||||
into the expanded `yy_transition'
|
||||
array. See notes in manual. */
|
||||
YYTD_STRUCT = 0x10 /**< data consists of yy_trans_info structs */
|
||||
};
|
||||
|
||||
/* The serialized tables header. */
|
||||
struct yytbl_hdr {
|
||||
flex_uint32_t th_magic; /**< Must be 0xF13C57B1 (comes from "Flex Table") */
|
||||
flex_uint32_t th_hsize; /**< Size of this header in bytes. */
|
||||
flex_uint32_t th_ssize; /**< Size of this dataset, in bytes, including header. */
|
||||
flex_uint16_t th_flags; /**< Currently unused, must be 0 */
|
||||
char *th_version; /**< Flex version string. NUL terminated. */
|
||||
char *th_name; /**< The name of this table set. NUL terminated. */
|
||||
};
|
||||
|
||||
/** A single serialized table */
|
||||
struct yytbl_data {
|
||||
flex_uint16_t td_id; /**< enum yytbl_id table identifier */
|
||||
flex_uint16_t td_flags; /**< how to interpret this data */
|
||||
flex_uint32_t td_hilen; /**< num elements in highest dimension array */
|
||||
flex_uint32_t td_lolen; /**< num elements in lowest dimension array */
|
||||
void *td_data; /**< table data */
|
||||
};
|
||||
#endif
|
||||
|
||||
/** Extract corresponding data size_t from td_flags */
|
||||
#ifndef YYTDFLAGS2BYTES
|
||||
#define YYTDFLAGS2BYTES(td_flags)\
|
||||
(((td_flags) & YYTD_DATA8)\
|
||||
? sizeof(flex_int8_t)\
|
||||
:(((td_flags) & YYTD_DATA16)\
|
||||
? sizeof(flex_int16_t)\
|
||||
:sizeof(flex_int32_t)))
|
||||
#endif
|
||||
|
||||
#ifdef FLEX_SCANNER
|
||||
%not-for-header
|
||||
#endif
|
||||
yyskel_static flex_int32_t yytbl_calc_total_len (const struct yytbl_data *tbl);
|
||||
#ifdef FLEX_SCANNER
|
||||
%ok-for-header
|
||||
#endif
|
||||
|
||||
/* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */
|
853
contrib/flex/tblcmp.c
Normal file
853
contrib/flex/tblcmp.c
Normal file
@ -0,0 +1,853 @@
|
||||
/* tblcmp - table compression routines */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include "flexdef.h"
|
||||
|
||||
|
||||
/* declarations for functions that have forward references */
|
||||
|
||||
void mkentry PROTO ((register int *, int, int, int, int));
|
||||
void mkprot PROTO ((int[], int, int));
|
||||
void mktemplate PROTO ((int[], int, int));
|
||||
void mv2front PROTO ((int));
|
||||
int tbldiff PROTO ((int[], int, int[]));
|
||||
|
||||
|
||||
/* bldtbl - build table entries for dfa state
|
||||
*
|
||||
* synopsis
|
||||
* int state[numecs], statenum, totaltrans, comstate, comfreq;
|
||||
* bldtbl( state, statenum, totaltrans, comstate, comfreq );
|
||||
*
|
||||
* State is the statenum'th dfa state. It is indexed by equivalence class and
|
||||
* gives the number of the state to enter for a given equivalence class.
|
||||
* totaltrans is the total number of transitions out of the state. Comstate
|
||||
* is that state which is the destination of the most transitions out of State.
|
||||
* Comfreq is how many transitions there are out of State to Comstate.
|
||||
*
|
||||
* A note on terminology:
|
||||
* "protos" are transition tables which have a high probability of
|
||||
* either being redundant (a state processed later will have an identical
|
||||
* transition table) or nearly redundant (a state processed later will have
|
||||
* many of the same out-transitions). A "most recently used" queue of
|
||||
* protos is kept around with the hope that most states will find a proto
|
||||
* which is similar enough to be usable, and therefore compacting the
|
||||
* output tables.
|
||||
* "templates" are a special type of proto. If a transition table is
|
||||
* homogeneous or nearly homogeneous (all transitions go to the same
|
||||
* destination) then the odds are good that future states will also go
|
||||
* to the same destination state on basically the same character set.
|
||||
* These homogeneous states are so common when dealing with large rule
|
||||
* sets that they merit special attention. If the transition table were
|
||||
* simply made into a proto, then (typically) each subsequent, similar
|
||||
* state will differ from the proto for two out-transitions. One of these
|
||||
* out-transitions will be that character on which the proto does not go
|
||||
* to the common destination, and one will be that character on which the
|
||||
* state does not go to the common destination. Templates, on the other
|
||||
* hand, go to the common state on EVERY transition character, and therefore
|
||||
* cost only one difference.
|
||||
*/
|
||||
|
||||
void bldtbl (state, statenum, totaltrans, comstate, comfreq)
|
||||
int state[], statenum, totaltrans, comstate, comfreq;
|
||||
{
|
||||
int extptr, extrct[2][CSIZE + 1];
|
||||
int mindiff, minprot, i, d;
|
||||
|
||||
/* If extptr is 0 then the first array of extrct holds the result
|
||||
* of the "best difference" to date, which is those transitions
|
||||
* which occur in "state" but not in the proto which, to date,
|
||||
* has the fewest differences between itself and "state". If
|
||||
* extptr is 1 then the second array of extrct hold the best
|
||||
* difference. The two arrays are toggled between so that the
|
||||
* best difference to date can be kept around and also a difference
|
||||
* just created by checking against a candidate "best" proto.
|
||||
*/
|
||||
|
||||
extptr = 0;
|
||||
|
||||
/* If the state has too few out-transitions, don't bother trying to
|
||||
* compact its tables.
|
||||
*/
|
||||
|
||||
if ((totaltrans * 100) < (numecs * PROTO_SIZE_PERCENTAGE))
|
||||
mkentry (state, numecs, statenum, JAMSTATE, totaltrans);
|
||||
|
||||
else {
|
||||
/* "checkcom" is true if we should only check "state" against
|
||||
* protos which have the same "comstate" value.
|
||||
*/
|
||||
int checkcom =
|
||||
|
||||
comfreq * 100 > totaltrans * CHECK_COM_PERCENTAGE;
|
||||
|
||||
minprot = firstprot;
|
||||
mindiff = totaltrans;
|
||||
|
||||
if (checkcom) {
|
||||
/* Find first proto which has the same "comstate". */
|
||||
for (i = firstprot; i != NIL; i = protnext[i])
|
||||
if (protcomst[i] == comstate) {
|
||||
minprot = i;
|
||||
mindiff = tbldiff (state, minprot,
|
||||
extrct[extptr]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* Since we've decided that the most common destination
|
||||
* out of "state" does not occur with a high enough
|
||||
* frequency, we set the "comstate" to zero, assuring
|
||||
* that if this state is entered into the proto list,
|
||||
* it will not be considered a template.
|
||||
*/
|
||||
comstate = 0;
|
||||
|
||||
if (firstprot != NIL) {
|
||||
minprot = firstprot;
|
||||
mindiff = tbldiff (state, minprot,
|
||||
extrct[extptr]);
|
||||
}
|
||||
}
|
||||
|
||||
/* We now have the first interesting proto in "minprot". If
|
||||
* it matches within the tolerances set for the first proto,
|
||||
* we don't want to bother scanning the rest of the proto list
|
||||
* to see if we have any other reasonable matches.
|
||||
*/
|
||||
|
||||
if (mindiff * 100 >
|
||||
totaltrans * FIRST_MATCH_DIFF_PERCENTAGE) {
|
||||
/* Not a good enough match. Scan the rest of the
|
||||
* protos.
|
||||
*/
|
||||
for (i = minprot; i != NIL; i = protnext[i]) {
|
||||
d = tbldiff (state, i, extrct[1 - extptr]);
|
||||
if (d < mindiff) {
|
||||
extptr = 1 - extptr;
|
||||
mindiff = d;
|
||||
minprot = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the proto we've decided on as our best bet is close
|
||||
* enough to the state we want to match to be usable.
|
||||
*/
|
||||
|
||||
if (mindiff * 100 >
|
||||
totaltrans * ACCEPTABLE_DIFF_PERCENTAGE) {
|
||||
/* No good. If the state is homogeneous enough,
|
||||
* we make a template out of it. Otherwise, we
|
||||
* make a proto.
|
||||
*/
|
||||
|
||||
if (comfreq * 100 >=
|
||||
totaltrans * TEMPLATE_SAME_PERCENTAGE)
|
||||
mktemplate (state, statenum,
|
||||
comstate);
|
||||
|
||||
else {
|
||||
mkprot (state, statenum, comstate);
|
||||
mkentry (state, numecs, statenum,
|
||||
JAMSTATE, totaltrans);
|
||||
}
|
||||
}
|
||||
|
||||
else { /* use the proto */
|
||||
mkentry (extrct[extptr], numecs, statenum,
|
||||
prottbl[minprot], mindiff);
|
||||
|
||||
/* If this state was sufficiently different from the
|
||||
* proto we built it from, make it, too, a proto.
|
||||
*/
|
||||
|
||||
if (mindiff * 100 >=
|
||||
totaltrans * NEW_PROTO_DIFF_PERCENTAGE)
|
||||
mkprot (state, statenum, comstate);
|
||||
|
||||
/* Since mkprot added a new proto to the proto queue,
|
||||
* it's possible that "minprot" is no longer on the
|
||||
* proto queue (if it happened to have been the last
|
||||
* entry, it would have been bumped off). If it's
|
||||
* not there, then the new proto took its physical
|
||||
* place (though logically the new proto is at the
|
||||
* beginning of the queue), so in that case the
|
||||
* following call will do nothing.
|
||||
*/
|
||||
|
||||
mv2front (minprot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* cmptmps - compress template table entries
|
||||
*
|
||||
* Template tables are compressed by using the 'template equivalence
|
||||
* classes', which are collections of transition character equivalence
|
||||
* classes which always appear together in templates - really meta-equivalence
|
||||
* classes.
|
||||
*/
|
||||
|
||||
void cmptmps ()
|
||||
{
|
||||
int tmpstorage[CSIZE + 1];
|
||||
register int *tmp = tmpstorage, i, j;
|
||||
int totaltrans, trans;
|
||||
|
||||
peakpairs = numtemps * numecs + tblend;
|
||||
|
||||
if (usemecs) {
|
||||
/* Create equivalence classes based on data gathered on
|
||||
* template transitions.
|
||||
*/
|
||||
nummecs = cre8ecs (tecfwd, tecbck, numecs);
|
||||
}
|
||||
|
||||
else
|
||||
nummecs = numecs;
|
||||
|
||||
while (lastdfa + numtemps + 1 >= current_max_dfas)
|
||||
increase_max_dfas ();
|
||||
|
||||
/* Loop through each template. */
|
||||
|
||||
for (i = 1; i <= numtemps; ++i) {
|
||||
/* Number of non-jam transitions out of this template. */
|
||||
totaltrans = 0;
|
||||
|
||||
for (j = 1; j <= numecs; ++j) {
|
||||
trans = tnxt[numecs * i + j];
|
||||
|
||||
if (usemecs) {
|
||||
/* The absolute value of tecbck is the
|
||||
* meta-equivalence class of a given
|
||||
* equivalence class, as set up by cre8ecs().
|
||||
*/
|
||||
if (tecbck[j] > 0) {
|
||||
tmp[tecbck[j]] = trans;
|
||||
|
||||
if (trans > 0)
|
||||
++totaltrans;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
tmp[j] = trans;
|
||||
|
||||
if (trans > 0)
|
||||
++totaltrans;
|
||||
}
|
||||
}
|
||||
|
||||
/* It is assumed (in a rather subtle way) in the skeleton
|
||||
* that if we're using meta-equivalence classes, the def[]
|
||||
* entry for all templates is the jam template, i.e.,
|
||||
* templates never default to other non-jam table entries
|
||||
* (e.g., another template)
|
||||
*/
|
||||
|
||||
/* Leave room for the jam-state after the last real state. */
|
||||
mkentry (tmp, nummecs, lastdfa + i + 1, JAMSTATE,
|
||||
totaltrans);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* expand_nxt_chk - expand the next check arrays */
|
||||
|
||||
void expand_nxt_chk ()
|
||||
{
|
||||
register int old_max = current_max_xpairs;
|
||||
|
||||
current_max_xpairs += MAX_XPAIRS_INCREMENT;
|
||||
|
||||
++num_reallocs;
|
||||
|
||||
nxt = reallocate_integer_array (nxt, current_max_xpairs);
|
||||
chk = reallocate_integer_array (chk, current_max_xpairs);
|
||||
|
||||
zero_out ((char *) (chk + old_max),
|
||||
(size_t) (MAX_XPAIRS_INCREMENT * sizeof (int)));
|
||||
}
|
||||
|
||||
|
||||
/* find_table_space - finds a space in the table for a state to be placed
|
||||
*
|
||||
* synopsis
|
||||
* int *state, numtrans, block_start;
|
||||
* int find_table_space();
|
||||
*
|
||||
* block_start = find_table_space( state, numtrans );
|
||||
*
|
||||
* State is the state to be added to the full speed transition table.
|
||||
* Numtrans is the number of out-transitions for the state.
|
||||
*
|
||||
* find_table_space() returns the position of the start of the first block (in
|
||||
* chk) able to accommodate the state
|
||||
*
|
||||
* In determining if a state will or will not fit, find_table_space() must take
|
||||
* into account the fact that an end-of-buffer state will be added at [0],
|
||||
* and an action number will be added in [-1].
|
||||
*/
|
||||
|
||||
int find_table_space (state, numtrans)
|
||||
int *state, numtrans;
|
||||
{
|
||||
/* Firstfree is the position of the first possible occurrence of two
|
||||
* consecutive unused records in the chk and nxt arrays.
|
||||
*/
|
||||
register int i;
|
||||
register int *state_ptr, *chk_ptr;
|
||||
register int *ptr_to_last_entry_in_state;
|
||||
|
||||
/* If there are too many out-transitions, put the state at the end of
|
||||
* nxt and chk.
|
||||
*/
|
||||
if (numtrans > MAX_XTIONS_FULL_INTERIOR_FIT) {
|
||||
/* If table is empty, return the first available spot in
|
||||
* chk/nxt, which should be 1.
|
||||
*/
|
||||
if (tblend < 2)
|
||||
return 1;
|
||||
|
||||
/* Start searching for table space near the end of
|
||||
* chk/nxt arrays.
|
||||
*/
|
||||
i = tblend - numecs;
|
||||
}
|
||||
|
||||
else
|
||||
/* Start searching for table space from the beginning
|
||||
* (skipping only the elements which will definitely not
|
||||
* hold the new state).
|
||||
*/
|
||||
i = firstfree;
|
||||
|
||||
while (1) { /* loops until a space is found */
|
||||
while (i + numecs >= current_max_xpairs)
|
||||
expand_nxt_chk ();
|
||||
|
||||
/* Loops until space for end-of-buffer and action number
|
||||
* are found.
|
||||
*/
|
||||
while (1) {
|
||||
/* Check for action number space. */
|
||||
if (chk[i - 1] == 0) {
|
||||
/* Check for end-of-buffer space. */
|
||||
if (chk[i] == 0)
|
||||
break;
|
||||
|
||||
else
|
||||
/* Since i != 0, there is no use
|
||||
* checking to see if (++i) - 1 == 0,
|
||||
* because that's the same as i == 0,
|
||||
* so we skip a space.
|
||||
*/
|
||||
i += 2;
|
||||
}
|
||||
|
||||
else
|
||||
++i;
|
||||
|
||||
while (i + numecs >= current_max_xpairs)
|
||||
expand_nxt_chk ();
|
||||
}
|
||||
|
||||
/* If we started search from the beginning, store the new
|
||||
* firstfree for the next call of find_table_space().
|
||||
*/
|
||||
if (numtrans <= MAX_XTIONS_FULL_INTERIOR_FIT)
|
||||
firstfree = i + 1;
|
||||
|
||||
/* Check to see if all elements in chk (and therefore nxt)
|
||||
* that are needed for the new state have not yet been taken.
|
||||
*/
|
||||
|
||||
state_ptr = &state[1];
|
||||
ptr_to_last_entry_in_state = &chk[i + numecs + 1];
|
||||
|
||||
for (chk_ptr = &chk[i + 1];
|
||||
chk_ptr != ptr_to_last_entry_in_state; ++chk_ptr)
|
||||
if (*(state_ptr++) != 0 && *chk_ptr != 0)
|
||||
break;
|
||||
|
||||
if (chk_ptr == ptr_to_last_entry_in_state)
|
||||
return i;
|
||||
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* inittbl - initialize transition tables
|
||||
*
|
||||
* Initializes "firstfree" to be one beyond the end of the table. Initializes
|
||||
* all "chk" entries to be zero.
|
||||
*/
|
||||
void inittbl ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
zero_out ((char *) chk,
|
||||
|
||||
(size_t) (current_max_xpairs * sizeof (int)));
|
||||
|
||||
tblend = 0;
|
||||
firstfree = tblend + 1;
|
||||
numtemps = 0;
|
||||
|
||||
if (usemecs) {
|
||||
/* Set up doubly-linked meta-equivalence classes; these
|
||||
* are sets of equivalence classes which all have identical
|
||||
* transitions out of TEMPLATES.
|
||||
*/
|
||||
|
||||
tecbck[1] = NIL;
|
||||
|
||||
for (i = 2; i <= numecs; ++i) {
|
||||
tecbck[i] = i - 1;
|
||||
tecfwd[i - 1] = i;
|
||||
}
|
||||
|
||||
tecfwd[numecs] = NIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* mkdeftbl - make the default, "jam" table entries */
|
||||
|
||||
void mkdeftbl ()
|
||||
{
|
||||
int i;
|
||||
|
||||
jamstate = lastdfa + 1;
|
||||
|
||||
++tblend; /* room for transition on end-of-buffer character */
|
||||
|
||||
while (tblend + numecs >= current_max_xpairs)
|
||||
expand_nxt_chk ();
|
||||
|
||||
/* Add in default end-of-buffer transition. */
|
||||
nxt[tblend] = end_of_buffer_state;
|
||||
chk[tblend] = jamstate;
|
||||
|
||||
for (i = 1; i <= numecs; ++i) {
|
||||
nxt[tblend + i] = 0;
|
||||
chk[tblend + i] = jamstate;
|
||||
}
|
||||
|
||||
jambase = tblend;
|
||||
|
||||
base[jamstate] = jambase;
|
||||
def[jamstate] = 0;
|
||||
|
||||
tblend += numecs;
|
||||
++numtemps;
|
||||
}
|
||||
|
||||
|
||||
/* mkentry - create base/def and nxt/chk entries for transition array
|
||||
*
|
||||
* synopsis
|
||||
* int state[numchars + 1], numchars, statenum, deflink, totaltrans;
|
||||
* mkentry( state, numchars, statenum, deflink, totaltrans );
|
||||
*
|
||||
* "state" is a transition array "numchars" characters in size, "statenum"
|
||||
* is the offset to be used into the base/def tables, and "deflink" is the
|
||||
* entry to put in the "def" table entry. If "deflink" is equal to
|
||||
* "JAMSTATE", then no attempt will be made to fit zero entries of "state"
|
||||
* (i.e., jam entries) into the table. It is assumed that by linking to
|
||||
* "JAMSTATE" they will be taken care of. In any case, entries in "state"
|
||||
* marking transitions to "SAME_TRANS" are treated as though they will be
|
||||
* taken care of by whereever "deflink" points. "totaltrans" is the total
|
||||
* number of transitions out of the state. If it is below a certain threshold,
|
||||
* the tables are searched for an interior spot that will accommodate the
|
||||
* state array.
|
||||
*/
|
||||
|
||||
void mkentry (state, numchars, statenum, deflink, totaltrans)
|
||||
register int *state;
|
||||
int numchars, statenum, deflink, totaltrans;
|
||||
{
|
||||
register int minec, maxec, i, baseaddr;
|
||||
int tblbase, tbllast;
|
||||
|
||||
if (totaltrans == 0) { /* there are no out-transitions */
|
||||
if (deflink == JAMSTATE)
|
||||
base[statenum] = JAMSTATE;
|
||||
else
|
||||
base[statenum] = 0;
|
||||
|
||||
def[statenum] = deflink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (minec = 1; minec <= numchars; ++minec) {
|
||||
if (state[minec] != SAME_TRANS)
|
||||
if (state[minec] != 0 || deflink != JAMSTATE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (totaltrans == 1) {
|
||||
/* There's only one out-transition. Save it for later to fill
|
||||
* in holes in the tables.
|
||||
*/
|
||||
stack1 (statenum, minec, state[minec], deflink);
|
||||
return;
|
||||
}
|
||||
|
||||
for (maxec = numchars; maxec > 0; --maxec) {
|
||||
if (state[maxec] != SAME_TRANS)
|
||||
if (state[maxec] != 0 || deflink != JAMSTATE)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Whether we try to fit the state table in the middle of the table
|
||||
* entries we have already generated, or if we just take the state
|
||||
* table at the end of the nxt/chk tables, we must make sure that we
|
||||
* have a valid base address (i.e., non-negative). Note that
|
||||
* negative base addresses dangerous at run-time (because indexing
|
||||
* the nxt array with one and a low-valued character will access
|
||||
* memory before the start of the array.
|
||||
*/
|
||||
|
||||
/* Find the first transition of state that we need to worry about. */
|
||||
if (totaltrans * 100 <= numchars * INTERIOR_FIT_PERCENTAGE) {
|
||||
/* Attempt to squeeze it into the middle of the tables. */
|
||||
baseaddr = firstfree;
|
||||
|
||||
while (baseaddr < minec) {
|
||||
/* Using baseaddr would result in a negative base
|
||||
* address below; find the next free slot.
|
||||
*/
|
||||
for (++baseaddr; chk[baseaddr] != 0; ++baseaddr) ;
|
||||
}
|
||||
|
||||
while (baseaddr + maxec - minec + 1 >= current_max_xpairs)
|
||||
expand_nxt_chk ();
|
||||
|
||||
for (i = minec; i <= maxec; ++i)
|
||||
if (state[i] != SAME_TRANS &&
|
||||
(state[i] != 0 || deflink != JAMSTATE) &&
|
||||
chk[baseaddr + i - minec] != 0) { /* baseaddr unsuitable - find another */
|
||||
for (++baseaddr;
|
||||
baseaddr < current_max_xpairs &&
|
||||
chk[baseaddr] != 0; ++baseaddr) ;
|
||||
|
||||
while (baseaddr + maxec - minec + 1 >=
|
||||
current_max_xpairs)
|
||||
expand_nxt_chk ();
|
||||
|
||||
/* Reset the loop counter so we'll start all
|
||||
* over again next time it's incremented.
|
||||
*/
|
||||
|
||||
i = minec - 1;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* Ensure that the base address we eventually generate is
|
||||
* non-negative.
|
||||
*/
|
||||
baseaddr = MAX (tblend + 1, minec);
|
||||
}
|
||||
|
||||
tblbase = baseaddr - minec;
|
||||
tbllast = tblbase + maxec;
|
||||
|
||||
while (tbllast + 1 >= current_max_xpairs)
|
||||
expand_nxt_chk ();
|
||||
|
||||
base[statenum] = tblbase;
|
||||
def[statenum] = deflink;
|
||||
|
||||
for (i = minec; i <= maxec; ++i)
|
||||
if (state[i] != SAME_TRANS)
|
||||
if (state[i] != 0 || deflink != JAMSTATE) {
|
||||
nxt[tblbase + i] = state[i];
|
||||
chk[tblbase + i] = statenum;
|
||||
}
|
||||
|
||||
if (baseaddr == firstfree)
|
||||
/* Find next free slot in tables. */
|
||||
for (++firstfree; chk[firstfree] != 0; ++firstfree) ;
|
||||
|
||||
tblend = MAX (tblend, tbllast);
|
||||
}
|
||||
|
||||
|
||||
/* mk1tbl - create table entries for a state (or state fragment) which
|
||||
* has only one out-transition
|
||||
*/
|
||||
|
||||
void mk1tbl (state, sym, onenxt, onedef)
|
||||
int state, sym, onenxt, onedef;
|
||||
{
|
||||
if (firstfree < sym)
|
||||
firstfree = sym;
|
||||
|
||||
while (chk[firstfree] != 0)
|
||||
if (++firstfree >= current_max_xpairs)
|
||||
expand_nxt_chk ();
|
||||
|
||||
base[state] = firstfree - sym;
|
||||
def[state] = onedef;
|
||||
chk[firstfree] = state;
|
||||
nxt[firstfree] = onenxt;
|
||||
|
||||
if (firstfree > tblend) {
|
||||
tblend = firstfree++;
|
||||
|
||||
if (firstfree >= current_max_xpairs)
|
||||
expand_nxt_chk ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* mkprot - create new proto entry */
|
||||
|
||||
void mkprot (state, statenum, comstate)
|
||||
int state[], statenum, comstate;
|
||||
{
|
||||
int i, slot, tblbase;
|
||||
|
||||
if (++numprots >= MSP || numecs * numprots >= PROT_SAVE_SIZE) {
|
||||
/* Gotta make room for the new proto by dropping last entry in
|
||||
* the queue.
|
||||
*/
|
||||
slot = lastprot;
|
||||
lastprot = protprev[lastprot];
|
||||
protnext[lastprot] = NIL;
|
||||
}
|
||||
|
||||
else
|
||||
slot = numprots;
|
||||
|
||||
protnext[slot] = firstprot;
|
||||
|
||||
if (firstprot != NIL)
|
||||
protprev[firstprot] = slot;
|
||||
|
||||
firstprot = slot;
|
||||
prottbl[slot] = statenum;
|
||||
protcomst[slot] = comstate;
|
||||
|
||||
/* Copy state into save area so it can be compared with rapidly. */
|
||||
tblbase = numecs * (slot - 1);
|
||||
|
||||
for (i = 1; i <= numecs; ++i)
|
||||
protsave[tblbase + i] = state[i];
|
||||
}
|
||||
|
||||
|
||||
/* mktemplate - create a template entry based on a state, and connect the state
|
||||
* to it
|
||||
*/
|
||||
|
||||
void mktemplate (state, statenum, comstate)
|
||||
int state[], statenum, comstate;
|
||||
{
|
||||
int i, numdiff, tmpbase, tmp[CSIZE + 1];
|
||||
Char transset[CSIZE + 1];
|
||||
int tsptr;
|
||||
|
||||
++numtemps;
|
||||
|
||||
tsptr = 0;
|
||||
|
||||
/* Calculate where we will temporarily store the transition table
|
||||
* of the template in the tnxt[] array. The final transition table
|
||||
* gets created by cmptmps().
|
||||
*/
|
||||
|
||||
tmpbase = numtemps * numecs;
|
||||
|
||||
if (tmpbase + numecs >= current_max_template_xpairs) {
|
||||
current_max_template_xpairs +=
|
||||
MAX_TEMPLATE_XPAIRS_INCREMENT;
|
||||
|
||||
++num_reallocs;
|
||||
|
||||
tnxt = reallocate_integer_array (tnxt,
|
||||
current_max_template_xpairs);
|
||||
}
|
||||
|
||||
for (i = 1; i <= numecs; ++i)
|
||||
if (state[i] == 0)
|
||||
tnxt[tmpbase + i] = 0;
|
||||
else {
|
||||
transset[tsptr++] = i;
|
||||
tnxt[tmpbase + i] = comstate;
|
||||
}
|
||||
|
||||
if (usemecs)
|
||||
mkeccl (transset, tsptr, tecfwd, tecbck, numecs, 0);
|
||||
|
||||
mkprot (tnxt + tmpbase, -numtemps, comstate);
|
||||
|
||||
/* We rely on the fact that mkprot adds things to the beginning
|
||||
* of the proto queue.
|
||||
*/
|
||||
|
||||
numdiff = tbldiff (state, firstprot, tmp);
|
||||
mkentry (tmp, numecs, statenum, -numtemps, numdiff);
|
||||
}
|
||||
|
||||
|
||||
/* mv2front - move proto queue element to front of queue */
|
||||
|
||||
void mv2front (qelm)
|
||||
int qelm;
|
||||
{
|
||||
if (firstprot != qelm) {
|
||||
if (qelm == lastprot)
|
||||
lastprot = protprev[lastprot];
|
||||
|
||||
protnext[protprev[qelm]] = protnext[qelm];
|
||||
|
||||
if (protnext[qelm] != NIL)
|
||||
protprev[protnext[qelm]] = protprev[qelm];
|
||||
|
||||
protprev[qelm] = NIL;
|
||||
protnext[qelm] = firstprot;
|
||||
protprev[firstprot] = qelm;
|
||||
firstprot = qelm;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* place_state - place a state into full speed transition table
|
||||
*
|
||||
* State is the statenum'th state. It is indexed by equivalence class and
|
||||
* gives the number of the state to enter for a given equivalence class.
|
||||
* Transnum is the number of out-transitions for the state.
|
||||
*/
|
||||
|
||||
void place_state (state, statenum, transnum)
|
||||
int *state, statenum, transnum;
|
||||
{
|
||||
register int i;
|
||||
register int *state_ptr;
|
||||
int position = find_table_space (state, transnum);
|
||||
|
||||
/* "base" is the table of start positions. */
|
||||
base[statenum] = position;
|
||||
|
||||
/* Put in action number marker; this non-zero number makes sure that
|
||||
* find_table_space() knows that this position in chk/nxt is taken
|
||||
* and should not be used for another accepting number in another
|
||||
* state.
|
||||
*/
|
||||
chk[position - 1] = 1;
|
||||
|
||||
/* Put in end-of-buffer marker; this is for the same purposes as
|
||||
* above.
|
||||
*/
|
||||
chk[position] = 1;
|
||||
|
||||
/* Place the state into chk and nxt. */
|
||||
state_ptr = &state[1];
|
||||
|
||||
for (i = 1; i <= numecs; ++i, ++state_ptr)
|
||||
if (*state_ptr != 0) {
|
||||
chk[position + i] = i;
|
||||
nxt[position + i] = *state_ptr;
|
||||
}
|
||||
|
||||
if (position + numecs > tblend)
|
||||
tblend = position + numecs;
|
||||
}
|
||||
|
||||
|
||||
/* stack1 - save states with only one out-transition to be processed later
|
||||
*
|
||||
* If there's room for another state on the "one-transition" stack, the
|
||||
* state is pushed onto it, to be processed later by mk1tbl. If there's
|
||||
* no room, we process the sucker right now.
|
||||
*/
|
||||
|
||||
void stack1 (statenum, sym, nextstate, deflink)
|
||||
int statenum, sym, nextstate, deflink;
|
||||
{
|
||||
if (onesp >= ONE_STACK_SIZE - 1)
|
||||
mk1tbl (statenum, sym, nextstate, deflink);
|
||||
|
||||
else {
|
||||
++onesp;
|
||||
onestate[onesp] = statenum;
|
||||
onesym[onesp] = sym;
|
||||
onenext[onesp] = nextstate;
|
||||
onedef[onesp] = deflink;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* tbldiff - compute differences between two state tables
|
||||
*
|
||||
* "state" is the state array which is to be extracted from the pr'th
|
||||
* proto. "pr" is both the number of the proto we are extracting from
|
||||
* and an index into the save area where we can find the proto's complete
|
||||
* state table. Each entry in "state" which differs from the corresponding
|
||||
* entry of "pr" will appear in "ext".
|
||||
*
|
||||
* Entries which are the same in both "state" and "pr" will be marked
|
||||
* as transitions to "SAME_TRANS" in "ext". The total number of differences
|
||||
* between "state" and "pr" is returned as function value. Note that this
|
||||
* number is "numecs" minus the number of "SAME_TRANS" entries in "ext".
|
||||
*/
|
||||
|
||||
int tbldiff (state, pr, ext)
|
||||
int state[], pr, ext[];
|
||||
{
|
||||
register int i, *sp = state, *ep = ext, *protp;
|
||||
register int numdiff = 0;
|
||||
|
||||
protp = &protsave[numecs * (pr - 1)];
|
||||
|
||||
for (i = numecs; i > 0; --i) {
|
||||
if (*++protp == *++sp)
|
||||
*++ep = SAME_TRANS;
|
||||
else {
|
||||
*++ep = *sp;
|
||||
++numdiff;
|
||||
}
|
||||
}
|
||||
|
||||
return numdiff;
|
||||
}
|
1
contrib/flex/version.h
Normal file
1
contrib/flex/version.h
Normal file
@ -0,0 +1 @@
|
||||
#define FLEX_VERSION VERSION
|
211
contrib/flex/yylex.c
Normal file
211
contrib/flex/yylex.c
Normal file
@ -0,0 +1,211 @@
|
||||
/* yylex - scanner front-end for flex */
|
||||
|
||||
/* Copyright (c) 1990 The Regents of the University of California. */
|
||||
/* All rights reserved. */
|
||||
|
||||
/* This code is derived from software contributed to Berkeley by */
|
||||
/* Vern Paxson. */
|
||||
|
||||
/* The United States Government has rights in this work pursuant */
|
||||
/* to contract no. DE-AC03-76SF00098 between the United States */
|
||||
/* Department of Energy and the University of California. */
|
||||
|
||||
/* This file is part of flex. */
|
||||
|
||||
/* Redistribution and use in source and binary forms, with or without */
|
||||
/* modification, are permitted provided that the following conditions */
|
||||
/* are met: */
|
||||
|
||||
/* 1. Redistributions of source code must retain the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer. */
|
||||
/* 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* notice, this list of conditions and the following disclaimer in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
|
||||
/* Neither the name of the University nor the names of its contributors */
|
||||
/* may be used to endorse or promote products derived from this software */
|
||||
/* without specific prior written permission. */
|
||||
|
||||
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
|
||||
/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
|
||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
|
||||
/* PURPOSE. */
|
||||
|
||||
#include <ctype.h>
|
||||
#include "flexdef.h"
|
||||
#include "parse.h"
|
||||
|
||||
|
||||
/* yylex - scan for a regular expression token */
|
||||
|
||||
int yylex ()
|
||||
{
|
||||
int toktype;
|
||||
static int beglin = false;
|
||||
extern char *yytext;
|
||||
|
||||
if (eofseen)
|
||||
toktype = EOF;
|
||||
else
|
||||
toktype = flexscan ();
|
||||
|
||||
if (toktype == EOF || toktype == 0) {
|
||||
eofseen = 1;
|
||||
|
||||
if (sectnum == 1) {
|
||||
synerr (_("premature EOF"));
|
||||
sectnum = 2;
|
||||
toktype = SECTEND;
|
||||
}
|
||||
|
||||
else
|
||||
toktype = 0;
|
||||
}
|
||||
|
||||
if (trace) {
|
||||
if (beglin) {
|
||||
fprintf (stderr, "%d\t", num_rules + 1);
|
||||
beglin = 0;
|
||||
}
|
||||
|
||||
switch (toktype) {
|
||||
case '<':
|
||||
case '>':
|
||||
case '^':
|
||||
case '$':
|
||||
case '"':
|
||||
case '[':
|
||||
case ']':
|
||||
case '{':
|
||||
case '}':
|
||||
case '|':
|
||||
case '(':
|
||||
case ')':
|
||||
case '-':
|
||||
case '/':
|
||||
case '\\':
|
||||
case '?':
|
||||
case '.':
|
||||
case '*':
|
||||
case '+':
|
||||
case ',':
|
||||
(void) putc (toktype, stderr);
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
(void) putc ('\n', stderr);
|
||||
|
||||
if (sectnum == 2)
|
||||
beglin = 1;
|
||||
|
||||
break;
|
||||
|
||||
case SCDECL:
|
||||
fputs ("%s", stderr);
|
||||
break;
|
||||
|
||||
case XSCDECL:
|
||||
fputs ("%x", stderr);
|
||||
break;
|
||||
|
||||
case SECTEND:
|
||||
fputs ("%%\n", stderr);
|
||||
|
||||
/* We set beglin to be true so we'll start
|
||||
* writing out numbers as we echo rules.
|
||||
* flexscan() has already assigned sectnum.
|
||||
*/
|
||||
if (sectnum == 2)
|
||||
beglin = 1;
|
||||
|
||||
break;
|
||||
|
||||
case NAME:
|
||||
fprintf (stderr, "'%s'", nmstr);
|
||||
break;
|
||||
|
||||
case CHAR:
|
||||
switch (yylval) {
|
||||
case '<':
|
||||
case '>':
|
||||
case '^':
|
||||
case '$':
|
||||
case '"':
|
||||
case '[':
|
||||
case ']':
|
||||
case '{':
|
||||
case '}':
|
||||
case '|':
|
||||
case '(':
|
||||
case ')':
|
||||
case '-':
|
||||
case '/':
|
||||
case '\\':
|
||||
case '?':
|
||||
case '.':
|
||||
case '*':
|
||||
case '+':
|
||||
case ',':
|
||||
fprintf (stderr, "\\%c", yylval);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!isascii (yylval) || !isprint (yylval))
|
||||
fprintf (stderr,
|
||||
"\\%.3o",
|
||||
(unsigned int) yylval);
|
||||
else
|
||||
(void) putc (yylval, stderr);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NUMBER:
|
||||
fprintf (stderr, "%d", yylval);
|
||||
break;
|
||||
|
||||
case PREVCCL:
|
||||
fprintf (stderr, "[%d]", yylval);
|
||||
break;
|
||||
|
||||
case EOF_OP:
|
||||
fprintf (stderr, "<<EOF>>");
|
||||
break;
|
||||
|
||||
case OPTION_OP:
|
||||
fprintf (stderr, "%s ", yytext);
|
||||
break;
|
||||
|
||||
case OPT_OUTFILE:
|
||||
case OPT_PREFIX:
|
||||
case CCE_ALNUM:
|
||||
case CCE_ALPHA:
|
||||
case CCE_BLANK:
|
||||
case CCE_CNTRL:
|
||||
case CCE_DIGIT:
|
||||
case CCE_GRAPH:
|
||||
case CCE_LOWER:
|
||||
case CCE_PRINT:
|
||||
case CCE_PUNCT:
|
||||
case CCE_SPACE:
|
||||
case CCE_UPPER:
|
||||
case CCE_XDIGIT:
|
||||
fprintf (stderr, "%s", yytext);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
fprintf (stderr, _("End Marker\n"));
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (stderr,
|
||||
_
|
||||
("*Something Weird* - tok: %d val: %d\n"),
|
||||
toktype, yylval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return toktype;
|
||||
}
|
Loading…
Reference in New Issue
Block a user