Compare commits
39
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5a4784140 | ||
|
|
6ac17b25a5 | ||
|
|
565e5e0242 | ||
|
|
867d2b87d3 | ||
|
|
ef73c17b95 | ||
|
|
07d3ec5ae1 | ||
|
|
01629532c8 | ||
|
|
ad97489d26 | ||
|
|
e4b5e8ebcb | ||
|
|
43d5886fef | ||
|
|
86b559a5da | ||
|
|
0ab871f46a | ||
|
|
eb8ef3c631 | ||
|
|
8465475f78 | ||
|
|
08790a882e | ||
|
|
00b6fe5031 | ||
|
|
434cabae66 | ||
|
|
f8c2dde741 | ||
|
|
c8039f0a9d | ||
|
|
12f694d220 | ||
|
|
811b1f1848 | ||
|
|
d187b321d8 | ||
|
|
cfaa401d57 | ||
|
|
64a43c3ce7 | ||
|
|
b25cbfa7ab | ||
|
|
2f6763d30b | ||
|
|
983520a1d9 | ||
|
|
93177e87ad | ||
|
|
c65f295e3c | ||
|
|
b0842b1718 | ||
|
|
be6e927ae7 | ||
|
|
72bd5645aa | ||
|
|
c5f2a7cd94 | ||
|
|
a569144fb7 | ||
|
|
362966205f | ||
|
|
c967eee423 | ||
|
|
65b130a0e9 | ||
|
|
fbd958f453 | ||
|
|
0059765062 |
@@ -1134,6 +1134,13 @@ endif(BRLCAD_ENABLE_OPENCL)
|
||||
option(BRLCAD_ENABLE_SPR "Enable features requiring Screened Poisson Surface Reconstruction" OFF)
|
||||
mark_as_advanced(BRLCAD_ENABLE_SPR)
|
||||
|
||||
# Enable experimental support for binary attributes
|
||||
option(BRLCAD_ENABLE_BINARY_ATTRIBUTES "Enable support for binary attributes" OFF)
|
||||
mark_as_advanced(BRLCAD_ENABLE_BINARY_ATTRIBUTES)
|
||||
if(BRLCAD_ENABLE_BINARY_ATTRIBUTES)
|
||||
CONFIG_H_APPEND(BRLCAD "#define USE_BINARY_ATTRIBUTES 1\n")
|
||||
endif(BRLCAD_ENABLE_BINARY_ATTRIBUTES)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# The following are fine-grained options for enabling/disabling compiler
|
||||
# and source code definition settings. Typically these are set to
|
||||
|
||||
@@ -722,15 +722,6 @@ version if BRLCAD_BUNDLED_LIBS is also AUTO.
|
||||
Aliases: ENABLE_SPR
|
||||
|
||||
|
||||
--- BRLCAD_BSON ---
|
||||
|
||||
Option for enabling and disabling compilation of the Libbson library
|
||||
provided with BRL-CAD's source code. Default is BUNDLED, using
|
||||
the included other/src version.
|
||||
|
||||
Aliases: ENABLE_BSON
|
||||
|
||||
|
||||
--- BRLCAD_SC ---
|
||||
|
||||
Option for enabling and disabling compilation of the NIST Step Class
|
||||
|
||||
@@ -13,6 +13,8 @@ changes made. See document footer for additional details.
|
||||
--- 2016-07-XX Release 7.26.2 ---
|
||||
----------------------------------------------------------------------
|
||||
|
||||
* upgraded freetype to version 2.6.5 - Cliff Yapp
|
||||
* upgraded zlib to version 1.2.8 - Cliff Yapp
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
@@ -1494,6 +1494,9 @@ ARCHER
|
||||
ATTRIBUTES
|
||||
----------
|
||||
|
||||
* See src/libbu/TODO.binary_attributes for more info about
|
||||
bson based binary attribute work.
|
||||
|
||||
* attr command option to output to a file
|
||||
|
||||
* attr command change to only output non-standard attributes
|
||||
|
||||
@@ -190,10 +190,6 @@ do
|
||||
shift;;
|
||||
--disable-spr) options="$options -DBRLCAD_SPR=SYSTEM";
|
||||
shift;;
|
||||
--enable-bson) options="$options -DBRLCAD_BSON=BUNDLED";
|
||||
shift;;
|
||||
--disable-bson) options="$options -DBRLCAD_BSON=SYSTEM";
|
||||
shift;;
|
||||
--enable-scl) options="$options -DBRLCAD_SC=BUNDLED";
|
||||
shift;;
|
||||
--disable-scl) options="$options -DBRLCAD_SC=SYSTEM";
|
||||
|
||||
@@ -3,6 +3,8 @@ set(specifications_EN
|
||||
)
|
||||
ADD_DOCBOOK("HTML;PHP;PDF" specifications_EN specifications/en "")
|
||||
|
||||
CMAKEFILES(BRL_CAD_g_format_V6.xml)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
|
||||
+3
-3
@@ -44,8 +44,8 @@
|
||||
/** @file bg.h */
|
||||
/** @} */
|
||||
|
||||
#ifndef GM_H
|
||||
#define GM_H
|
||||
#ifndef BG_H
|
||||
#define BG_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
#include "bg/tri_ray.h"
|
||||
#include "bg/tri_tri.h"
|
||||
|
||||
#endif /* GM_H */
|
||||
#endif /* BG_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
+3
-3
@@ -18,8 +18,8 @@
|
||||
* information.
|
||||
*/
|
||||
|
||||
#ifndef DVEC_H
|
||||
#define DVEC_H
|
||||
#ifndef BN_DVEC_H
|
||||
#define BN_DVEC_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -207,7 +207,7 @@ extern "C++" {
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* DVEC_H */
|
||||
#endif /* BN_DVEC_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
+3
-3
@@ -30,8 +30,8 @@
|
||||
/** @{ */
|
||||
/** @file plot3.h */
|
||||
|
||||
#ifndef PLOT3_H
|
||||
#define PLOT3_H
|
||||
#ifndef BN_PLOT3_H
|
||||
#define BN_PLOT3_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -484,7 +484,7 @@ BN_EXPORT extern void BU_FORTRAN(f3vect, F3VECT)(FILE **fp,
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* PLOT3_H */
|
||||
#endif /* BN_PLOT3_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
+3
-3
@@ -26,8 +26,8 @@
|
||||
/** @{ */
|
||||
/** @file spm.h */
|
||||
|
||||
#ifndef SPM_H
|
||||
#define SPM_H
|
||||
#ifndef BN_SPM_H
|
||||
#define BN_SPM_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bn/defines.h"
|
||||
@@ -135,7 +135,7 @@ BN_EXPORT extern void bn_spm_dump(bn_spm_map_t *mp, int verbose);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SPM_H */
|
||||
#endif /* BN_SPM_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
+4
-4
@@ -25,14 +25,14 @@
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#if defined(USE_BINARY_ATTRIBUTES)
|
||||
# include "bson.h"
|
||||
#endif
|
||||
|
||||
#include "bu/defines.h"
|
||||
#include "bu/magic.h"
|
||||
#include "bu/vls.h"
|
||||
|
||||
#if defined(USE_BINARY_ATTRIBUTES)
|
||||
#include "bson.h"
|
||||
#endif
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
+3
-3
@@ -29,8 +29,8 @@
|
||||
* example).
|
||||
*
|
||||
*/
|
||||
#ifndef BVIEW_H
|
||||
#define BVIEW_H
|
||||
#ifndef DM_BVIEW_H
|
||||
#define DM_BVIEW_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bu/list.h"
|
||||
@@ -312,7 +312,7 @@ struct view_obj {
|
||||
};
|
||||
#define VIEW_OBJ_NULL ((struct view_obj *)0)
|
||||
|
||||
#endif /* BVIEW_H */
|
||||
#endif /* DM_BVIEW_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DM_DM_DESIGN_H
|
||||
#define DM_DM_DESIGN_H
|
||||
|
||||
/* Display Manager Types */
|
||||
#define DM_TYPE_BAD -1
|
||||
#define DM_TYPE_NULL 0
|
||||
@@ -201,7 +204,7 @@ DM_EXPORT extern int dm_set_type(dm_s *dmp, int dm_t);
|
||||
DM_EXPORT extern int dm_get_image(dm_s *dmp, icv_image_t *image);
|
||||
DM_EXPORT extern int dm_get_obj_image(dm_s *dmp, const char *handle, icv_image_t *image);
|
||||
|
||||
#endif /* DM_H */
|
||||
#endif /* DM_DM_DESIGN_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
/** @file dm_xvars.h
|
||||
*
|
||||
*/
|
||||
#ifndef DM_XVARS_H
|
||||
#define DM_XVARS_H
|
||||
#ifndef DM_DM_XVARS_H
|
||||
#define DM_DM_XVARS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -83,7 +83,7 @@ struct dm_xvars {
|
||||
int devbuttonrelease;
|
||||
};
|
||||
|
||||
#endif /* DM_XVARS_H */
|
||||
#endif /* DM_DM_XVARS_H */
|
||||
/** @} */
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
+50
-57
@@ -33,15 +33,16 @@
|
||||
#ifndef NMG_H
|
||||
#define NMG_H
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* interface headers */
|
||||
#include "bu/list.h"
|
||||
#include "bu/log.h"
|
||||
#include "bu/magic.h"
|
||||
#include "bu/ptbl.h"
|
||||
#include "vmath.h"
|
||||
|
||||
|
||||
#define DEBUG_PL_ANIM 0x00000001 /**< @brief 1 mged: animated evaluation */
|
||||
#define DEBUG_PL_SLOW 0x00000002 /**< @brief 2 mged: add delays to animation */
|
||||
#define DEBUG_GRAPHCL 0x00000004 /**< @brief 3 mged: graphic classification */
|
||||
@@ -513,18 +514,6 @@ struct vertexuse_a_cnurb {
|
||||
long index; /**< @brief struct # in this model */
|
||||
};
|
||||
|
||||
/**
|
||||
* storage allocation support
|
||||
* OBSOLETE
|
||||
*/
|
||||
#define NMG_GETSTRUCT(p, str) BU_GET(p, struct str)
|
||||
|
||||
/**
|
||||
* storage de-allocation support
|
||||
* OBSOLETE
|
||||
*/
|
||||
#define NMG_FREESTRUCT(ptr, str) BU_PUT(ptr, struct str)
|
||||
|
||||
|
||||
/*
|
||||
* Macros to create and destroy storage for the NMG data structures.
|
||||
@@ -537,52 +526,52 @@ struct vertexuse_a_cnurb {
|
||||
NMG_CK_MODEL(_m); (_p)->index = ((_m)->maxindex)++
|
||||
|
||||
|
||||
#define GET_MODEL(p, m) {NMG_GETSTRUCT(p, model); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_REGION(p, m) {NMG_GETSTRUCT(p, nmgregion); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_REGION_A(p, m) {NMG_GETSTRUCT(p, nmgregion_a); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_SHELL(p, m) {NMG_GETSTRUCT(p, shell); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_SHELL_A(p, m) {NMG_GETSTRUCT(p, shell_a); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_FACE(p, m) {NMG_GETSTRUCT(p, face); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_FACE_G_PLANE(p, m) {NMG_GETSTRUCT(p, face_g_plane); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_FACE_G_SNURB(p, m) {NMG_GETSTRUCT(p, face_g_snurb); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_FACEUSE(p, m) {NMG_GETSTRUCT(p, faceuse); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_LOOP(p, m) {NMG_GETSTRUCT(p, loop); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_LOOP_G(p, m) {NMG_GETSTRUCT(p, loop_g); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_LOOPUSE(p, m) {NMG_GETSTRUCT(p, loopuse); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_LOOPUSE_A(p, m) {NMG_GETSTRUCT(p, loopuse_a); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_EDGE(p, m) {NMG_GETSTRUCT(p, edge); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_EDGE_G_LSEG(p, m) {NMG_GETSTRUCT(p, edge_g_lseg); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_EDGE_G_CNURB(p, m) {NMG_GETSTRUCT(p, edge_g_cnurb); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_EDGEUSE(p, m) {NMG_GETSTRUCT(p, edgeuse); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEX(p, m) {NMG_GETSTRUCT(p, vertex); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEX_G(p, m) {NMG_GETSTRUCT(p, vertex_g); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEXUSE(p, m) {NMG_GETSTRUCT(p, vertexuse); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEXUSE_A_PLANE(p, m) {NMG_GETSTRUCT(p, vertexuse_a_plane); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEXUSE_A_CNURB(p, m) {NMG_GETSTRUCT(p, vertexuse_a_cnurb); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_MODEL(p, m) {BU_GET(p, struct model); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_REGION(p, m) {BU_GET(p, struct nmgregion); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_REGION_A(p, m) {BU_GET(p, struct nmgregion_a); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_SHELL(p, m) {BU_GET(p, struct shell); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_SHELL_A(p, m) {BU_GET(p, struct shell_a); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_FACE(p, m) {BU_GET(p, struct face); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_FACE_G_PLANE(p, m) {BU_GET(p, struct face_g_plane); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_FACE_G_SNURB(p, m) {BU_GET(p, struct face_g_snurb); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_FACEUSE(p, m) {BU_GET(p, struct faceuse); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_LOOP(p, m) {BU_GET(p, struct loop); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_LOOP_G(p, m) {BU_GET(p, struct loop_g); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_LOOPUSE(p, m) {BU_GET(p, struct loopuse); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_LOOPUSE_A(p, m) {BU_GET(p, struct loopuse_a); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_EDGE(p, m) {BU_GET(p, struct edge); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_EDGE_G_LSEG(p, m) {BU_GET(p, struct edge_g_lseg); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_EDGE_G_CNURB(p, m) {BU_GET(p, struct edge_g_cnurb); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_EDGEUSE(p, m) {BU_GET(p, struct edgeuse); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEX(p, m) {BU_GET(p, struct vertex); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEX_G(p, m) {BU_GET(p, struct vertex_g); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEXUSE(p, m) {BU_GET(p, struct vertexuse); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEXUSE_A_PLANE(p, m) {BU_GET(p, struct vertexuse_a_plane); NMG_INCR_INDEX(p, m);}
|
||||
#define GET_VERTEXUSE_A_CNURB(p, m) {BU_GET(p, struct vertexuse_a_cnurb); NMG_INCR_INDEX(p, m);}
|
||||
|
||||
|
||||
#define FREE_MODEL(p) NMG_FREESTRUCT(p, model)
|
||||
#define FREE_REGION(p) NMG_FREESTRUCT(p, nmgregion)
|
||||
#define FREE_REGION_A(p) NMG_FREESTRUCT(p, nmgregion_a)
|
||||
#define FREE_SHELL(p) NMG_FREESTRUCT(p, shell)
|
||||
#define FREE_SHELL_A(p) NMG_FREESTRUCT(p, shell_a)
|
||||
#define FREE_FACE(p) NMG_FREESTRUCT(p, face)
|
||||
#define FREE_FACE_G_PLANE(p) NMG_FREESTRUCT(p, face_g_plane)
|
||||
#define FREE_FACE_G_SNURB(p) NMG_FREESTRUCT(p, face_g_snurb)
|
||||
#define FREE_FACEUSE(p) NMG_FREESTRUCT(p, faceuse)
|
||||
#define FREE_LOOP(p) NMG_FREESTRUCT(p, loop)
|
||||
#define FREE_LOOP_G(p) NMG_FREESTRUCT(p, loop_g)
|
||||
#define FREE_LOOPUSE(p) NMG_FREESTRUCT(p, loopuse)
|
||||
#define FREE_LOOPUSE_A(p) NMG_FREESTRUCT(p, loopuse_a)
|
||||
#define FREE_EDGE(p) NMG_FREESTRUCT(p, edge)
|
||||
#define FREE_EDGE_G_LSEG(p) NMG_FREESTRUCT(p, edge_g_lseg)
|
||||
#define FREE_EDGE_G_CNURB(p) NMG_FREESTRUCT(p, edge_g_cnurb)
|
||||
#define FREE_EDGEUSE(p) NMG_FREESTRUCT(p, edgeuse)
|
||||
#define FREE_VERTEX(p) NMG_FREESTRUCT(p, vertex)
|
||||
#define FREE_VERTEX_G(p) NMG_FREESTRUCT(p, vertex_g)
|
||||
#define FREE_VERTEXUSE(p) NMG_FREESTRUCT(p, vertexuse)
|
||||
#define FREE_VERTEXUSE_A_PLANE(p) NMG_FREESTRUCT(p, vertexuse_a_plane)
|
||||
#define FREE_VERTEXUSE_A_CNURB(p) NMG_FREESTRUCT(p, vertexuse_a_cnurb)
|
||||
#define FREE_MODEL(p) BU_PUT(p, struct model)
|
||||
#define FREE_REGION(p) BU_PUT(p, struct nmgregion)
|
||||
#define FREE_REGION_A(p) BU_PUT(p, struct nmgregion_a)
|
||||
#define FREE_SHELL(p) BU_PUT(p, struct shell)
|
||||
#define FREE_SHELL_A(p) BU_PUT(p, struct shell_a)
|
||||
#define FREE_FACE(p) BU_PUT(p, struct face)
|
||||
#define FREE_FACE_G_PLANE(p) BU_PUT(p, struct face_g_plane)
|
||||
#define FREE_FACE_G_SNURB(p) BU_PUT(p, struct face_g_snurb)
|
||||
#define FREE_FACEUSE(p) BU_PUT(p, struct faceuse)
|
||||
#define FREE_LOOP(p) BU_PUT(p, struct loop)
|
||||
#define FREE_LOOP_G(p) BU_PUT(p, struct loop_g)
|
||||
#define FREE_LOOPUSE(p) BU_PUT(p, struct loopuse)
|
||||
#define FREE_LOOPUSE_A(p) BU_PUT(p, struct loopuse_a)
|
||||
#define FREE_EDGE(p) BU_PUT(p, struct edge)
|
||||
#define FREE_EDGE_G_LSEG(p) BU_PUT(p, struct edge_g_lseg)
|
||||
#define FREE_EDGE_G_CNURB(p) BU_PUT(p, struct edge_g_cnurb)
|
||||
#define FREE_EDGEUSE(p) BU_PUT(p, struct edgeuse)
|
||||
#define FREE_VERTEX(p) BU_PUT(p, struct vertex)
|
||||
#define FREE_VERTEX_G(p) BU_PUT(p, struct vertex_g)
|
||||
#define FREE_VERTEXUSE(p) BU_PUT(p, struct vertexuse)
|
||||
#define FREE_VERTEXUSE_A_PLANE(p) BU_PUT(p, struct vertexuse_a_plane)
|
||||
#define FREE_VERTEXUSE_A_CNURB(p) BU_PUT(p, struct vertexuse_a_cnurb)
|
||||
|
||||
|
||||
/**
|
||||
@@ -779,6 +768,10 @@ struct nmg_visit_handlers {
|
||||
void (*vis_vertex_g)(uint32_t *, void *, int);
|
||||
};
|
||||
|
||||
|
||||
extern int nmg_debug;
|
||||
|
||||
|
||||
#endif /* NMG_H */
|
||||
|
||||
/** @} */
|
||||
|
||||
+1523
File diff suppressed because it is too large
Load Diff
@@ -26,8 +26,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LIGHT_H
|
||||
#define LIGHT_H
|
||||
#ifndef OPTICAL_LIGHT_H
|
||||
#define OPTICAL_LIGHT_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -90,7 +90,7 @@ OPTICAL_EXPORT extern void light_obs(struct application *ap, struct shadework *s
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* LIGHT_H */
|
||||
#endif /* OPTICAL_LIGHT_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
/** @file plastic.h
|
||||
*
|
||||
*/
|
||||
#ifndef PLASTIC_H
|
||||
#define PLASTIC_H
|
||||
#ifndef OPTICAL_PLASTIC_H
|
||||
#define OPTICAL_PLASTIC_H
|
||||
|
||||
#define PL_NULL ((struct phong_specific *)0)
|
||||
#define PL_O(m) offsetof(struct phong_specific, m)
|
||||
@@ -43,7 +43,7 @@ struct phong_specific {
|
||||
};
|
||||
|
||||
extern struct bu_structparse phong_parse[];
|
||||
#endif
|
||||
#endif /* OPTICAL_PLASTIC_H */
|
||||
/** @} */
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHADEFUNCS_H
|
||||
#define SHADEFUNCS_H
|
||||
#ifndef OPTICAL_SHADEFUNCS_H
|
||||
#define OPTICAL_SHADEFUNCS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -96,7 +96,7 @@ OPTICAL_EXPORT extern struct mfuncs *load_dynamic_shader(const char *material);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SHADEFUNCS_H */
|
||||
#endif /* OPTICAL_SHADEFUNCS_H */
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHADEWORK_H
|
||||
#define SHADEWORK_H
|
||||
#ifndef OPTICAL_SHADEWORK_H
|
||||
#define OPTICAL_SHADEWORK_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bn/tabdata.h"
|
||||
@@ -76,7 +76,7 @@ extern void pr_shadework(const char *str, const struct shadework *swp);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SHADEWORK_H */
|
||||
#endif /* OPTICAL_SHADEWORK_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ARB_EDIT_H
|
||||
#define ARB_EDIT_H
|
||||
#ifndef RT_ARB_EDIT_H
|
||||
#define RT_ARB_EDIT_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bn.h"
|
||||
@@ -441,7 +441,7 @@ arb_edit(struct rt_arb_internal *arb, fastf_t peqn[7][4], int edge, int newedge,
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ARB_EDIT_H */
|
||||
#endif /* RT_ARB_EDIT_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
+3
-3
@@ -61,8 +61,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DB_H
|
||||
#define DB_H
|
||||
#ifndef RT_DB4_H
|
||||
#define RT_DB4_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -489,7 +489,7 @@ DEPRECATED void rt_dbmat_mat(dbfloat_t *dbp, const fastf_t *ff);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* DB_H */
|
||||
#endif /* RT_DB4_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
+3
-3
@@ -26,8 +26,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DB5_H
|
||||
#define DB5_H
|
||||
#ifndef RT_DB5_H
|
||||
#define RT_DB5_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -231,7 +231,7 @@ RT_EXPORT extern const unsigned char *db5_get_raw_internal_ptr(struct db5_raw_in
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* DB5_H */
|
||||
#endif /* RT_DB5_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
+3
-3
@@ -27,8 +27,8 @@
|
||||
* this message goes away.
|
||||
*
|
||||
*/
|
||||
#ifndef RTFUNC_H
|
||||
#define RTFUNC_H
|
||||
#ifndef RT_FUNC_H
|
||||
#define RT_FUNC_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -179,7 +179,7 @@ RT_EXPORT extern int rt_obj_mirror(struct rt_db_internal *ip, const plane_t *pla
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* RTFUNC_H */
|
||||
#endif /* RT_FUNC_H */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
+3
-3
@@ -28,8 +28,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NURB_H
|
||||
#define NURB_H
|
||||
#ifndef RT_NURB_H
|
||||
#define RT_NURB_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -284,7 +284,7 @@ RT_EXPORT extern void rt_nurb_map_oslo(struct oslo_mat *oslo,
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* NURB_H */
|
||||
#endif /* RT_NURB_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
|
||||
+3
-3
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TIE_H
|
||||
#define TIE_H
|
||||
#ifndef RT_TIE_H
|
||||
#define RT_TIE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -154,7 +154,7 @@ RT_EXPORT extern void TIE_VAL(tie_push)(struct tie_s *tie, TIE_3 **tlist, unsign
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* TIE_H */
|
||||
#endif /* RT_TIE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# From https://github.com/mongodb/mongo-c-driver/blob/master/build/cmake/FindBSON.cmake
|
||||
# License: Apache License Version 2.0, January 2004
|
||||
|
||||
# Read-Only variables:
|
||||
# BSON_FOUND - system has the BSON library
|
||||
# BSON_INCLUDE_DIR - the BSON include directory
|
||||
# BSON_LIBRARIES - The libraries needed to use BSON
|
||||
# BSON_VERSION - This is set to $major.$minor.$revision$path (eg. 0.4.1)
|
||||
|
||||
if (UNIX)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(_BSON QUIET libbson-1.0)
|
||||
endif ()
|
||||
|
||||
find_path(BSON_INCLUDE_DIR
|
||||
NAMES
|
||||
libbson-1.0/bson.h
|
||||
HINTS
|
||||
${BSON_ROOT_DIR}
|
||||
${_BSON_INCLUDEDIR}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
set(BSON_INCLUDE_DIR "${BSON_INCLUDE_DIR}/libbson-1.0")
|
||||
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
if(MSVC)
|
||||
find_library(BSON
|
||||
NAMES
|
||||
"bson-1.0"
|
||||
HINTS
|
||||
${BSON_ROOT_DIR}
|
||||
PATH_SUFFIXES
|
||||
bin
|
||||
lib
|
||||
)
|
||||
|
||||
mark_as_advanced(BSON)
|
||||
set(BSON_LIBRARIES ${BSON} ws2_32)
|
||||
else()
|
||||
# bother supporting this?
|
||||
endif()
|
||||
else()
|
||||
|
||||
find_library(BSON_LIBRARY
|
||||
NAMES
|
||||
bson-1.0
|
||||
HINTS
|
||||
${_BSON_LIBDIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
mark_as_advanced(BSON_LIBRARY)
|
||||
|
||||
find_package (Threads REQUIRED)
|
||||
|
||||
set(BSON_LIBRARIES ${BSON_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
endif()
|
||||
|
||||
if (BSON_INCLUDE_DIR)
|
||||
if (_BSON_VERSION)
|
||||
set(BSON_VERSION "${_BSON_VERSION}")
|
||||
elseif(BSON_INCLUDE_DIR AND EXISTS "${BSON_INCLUDE_DIR}/bson-version.h")
|
||||
file(STRINGS "${BSON_INCLUDE_DIR}/bson-version.h" bson_version_str
|
||||
REGEX "^#define[\t ]+BSON_VERSION[\t ]+\([0-9.]+\)[\t ]+$")
|
||||
|
||||
string(REGEX REPLACE "^.*BSON_VERSION[\t ]+\([0-9.]+\)[\t ]+$"
|
||||
"\\1" BSON_VERSION "${bson_version_str}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if (BSON_VERSION)
|
||||
find_package_handle_standard_args(BSON
|
||||
REQUIRED_VARS
|
||||
BSON_LIBRARIES
|
||||
BSON_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
BSON_VERSION
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find BSON version"
|
||||
)
|
||||
else ()
|
||||
find_package_handle_standard_args(BSON "Could NOT find BSON"
|
||||
BSON_LIBRARIES
|
||||
BSON_INCLUDE_DIR
|
||||
)
|
||||
endif ()
|
||||
|
||||
mark_as_advanced(BSON_INCLUDE_DIR BSON_LIBRARIES)
|
||||
@@ -0,0 +1,100 @@
|
||||
# F I N D G E C O D E . C M A K E
|
||||
# BRL-CAD
|
||||
#
|
||||
# Copyright (c) 2011-2014 United States Government as represented by
|
||||
# the U.S. Army Research Laboratory.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 3. The name of the author may not be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
###
|
||||
# - Find Gecode constraint programming libraries
|
||||
#
|
||||
# The following variables are set:
|
||||
#
|
||||
# GECODE_INCLUDE_DIR
|
||||
# GECODE_LIBRARIES
|
||||
|
||||
find_path(GECODE_INCLUDE_DIR gecode/search.hh)
|
||||
|
||||
find_library(GECODE_SUPPORT_LIB NAMES gecodesupport)
|
||||
find_library(GECODE_KERNEL_LIB NAMES gecodekernel)
|
||||
find_library(GECODE_SEARCH_LIB NAMES gecodesearch)
|
||||
find_library(GECODE_INT_LIB NAMES gecodeint)
|
||||
find_library(GECODE_SET_LIB NAMES gecodeset)
|
||||
find_library(GECODE_FLOAT_LIB NAMES gecodefloat)
|
||||
find_library(GECODE_MINIMODEL_LIB NAMES gecodeminimodel)
|
||||
find_library(GECODE_DRIVER_LIB NAMES gecodedriver)
|
||||
find_library(GECODE_FLATZINC_LIB NAMES gecodeflatzinc)
|
||||
|
||||
set(GECODE_LIBRARIES
|
||||
${GECODE_SUPPORT_LIB}
|
||||
${GECODE_KERNEL_LIB}
|
||||
${GECODE_SEARCH_LIB}
|
||||
${GECODE_INT_LIB}
|
||||
${GECODE_SET_LIB}
|
||||
${GECODE_FLOAT_LIB}
|
||||
${GECODE_MINIMODEL_LIB}
|
||||
${GECODE_DRIVER_LIB}
|
||||
${GECODE_FLATZINC_LIB}
|
||||
)
|
||||
|
||||
set(GECODE_LIBRARIES "${GECODE_LIBRARIES}" CACHE STRING "Gecode libraries")
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GECODE DEFAULT_MSG
|
||||
GECODE_SUPPORT_LIB
|
||||
GECODE_KERNEL_LIB
|
||||
GECODE_SEARCH_LIB
|
||||
GECODE_INT_LIB
|
||||
GECODE_SET_LIB
|
||||
GECODE_FLOAT_LIB
|
||||
GECODE_MINIMODEL_LIB
|
||||
GECODE_DRIVER_LIB
|
||||
GECODE_FLATZINC_LIB
|
||||
)
|
||||
|
||||
mark_as_advanced(
|
||||
GECODE_SUPPORT_LIB
|
||||
GECODE_KERNEL_LIB
|
||||
GECODE_SEARCH_LIB
|
||||
GECODE_INT_LIB
|
||||
GECODE_SET_LIB
|
||||
GECODE_FLOAT_LIB
|
||||
GECODE_MINIMODEL_LIB
|
||||
GECODE_DRIVER_LIB
|
||||
GECODE_FLATZINC_LIB
|
||||
)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
@@ -49,6 +49,7 @@ include(CMakeParseArguments)
|
||||
# [RESET_VARS var1 var2 ...]
|
||||
# [ALIASES alias1 alias2 ...]
|
||||
# [FLAGS flag1 flag2 ...]
|
||||
# [UNDOCUMENTED]
|
||||
# )
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@@ -72,7 +73,7 @@ macro(THIRD_PARTY dir varname_root build_target description)
|
||||
|
||||
if(${ARGC} GREATER 3)
|
||||
# Parse extra arguments
|
||||
CMAKE_PARSE_ARGUMENTS(${varname_root} "" "FIND_NAME;FIND_VERSION" "FIND_COMPONENTS;REQUIRED_VARS;RESET_VARS;ALIASES;FLAGS" ${ARGN})
|
||||
CMAKE_PARSE_ARGUMENTS(${varname_root} "UNDOCUMENTED" "FIND_NAME;FIND_VERSION" "FIND_COMPONENTS;REQUIRED_VARS;RESET_VARS;ALIASES;FLAGS" ${ARGN})
|
||||
endif(${ARGC} GREATER 3)
|
||||
if(NOT ${varname_root}_FIND_NAME)
|
||||
set(${varname_root}_FIND_NAME ${varname_root})
|
||||
@@ -262,8 +263,10 @@ macro(THIRD_PARTY dir varname_root build_target description)
|
||||
CMAKEFILES(${dir})
|
||||
endif(${CMAKE_PROJECT_NAME}_${varname_root}_BUILD)
|
||||
|
||||
OPTION_ALIASES("${CMAKE_PROJECT_NAME}_${varname_root}" "${varname_root}_ALIASES" "ABS")
|
||||
OPTION_DESCRIPTION("${CMAKE_PROJECT_NAME}_${varname_root}" "${varname_root}_ALIASES" "${description}")
|
||||
if(NOT ${varname_root}_UNDOCUMENTED)
|
||||
OPTION_ALIASES("${CMAKE_PROJECT_NAME}_${varname_root}" "${varname_root}_ALIASES" "ABS")
|
||||
OPTION_DESCRIPTION("${CMAKE_PROJECT_NAME}_${varname_root}" "${varname_root}_ALIASES" "${description}")
|
||||
endif(NOT ${varname_root}_UNDOCUMENTED)
|
||||
|
||||
# For drop-down menus in CMake gui - set STRINGS property
|
||||
set_property(CACHE ${CMAKE_PROJECT_NAME}_${varname_root} PROPERTY STRINGS AUTO BUNDLED SYSTEM)
|
||||
|
||||
+146
-65
@@ -29,24 +29,32 @@
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cmake_policy(SET CMP0064 OLD)
|
||||
|
||||
# The purpose of this logic is to scan a set of C/C++ source files to identify
|
||||
# all of the variables the CMake configure process may need to set.
|
||||
|
||||
# The global property C_DEFINE_VARS will hold the list of defined variables
|
||||
# found.
|
||||
|
||||
# TODO - Use https://sourceforge.net/p/predef/wiki/Home/ to create more
|
||||
# comprehensive and less ad-hoc lists of flags for OS, arch, etc.
|
||||
|
||||
# A user can suppress consideration of definitions that match one or a set of
|
||||
# patterns by appending those patterns to the C_DEFINE_SKIPVARS global
|
||||
# property. There are some "standard" patterns that are automatically skipped
|
||||
# patterns. There are some "standard" patterns that are automatically skipped
|
||||
# - tests matching the "header guard" pattern are skipped, as are defines
|
||||
# matching the "EXPORT" and "IMPORT" substrings, operating system and compiler
|
||||
# identifiers, and various other flags that do not typically need user-defined
|
||||
# configure stage testing.
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_SKIPVARS ".*EXPORT.*")
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_SKIPVARS ".*IMPORT.*")
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_SKIPPATTERNS ".*EXPORT.*")
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_SKIPPATTERNS ".*IMPORT.*")
|
||||
|
||||
function(autoheader_ignore_define def)
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_SKIPVARS ".*[ (\t]+${def}[ )\t$]*.*")
|
||||
if("${def}" MATCHES ".*[*].*")
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_SKIPPATTERNS "${def}")
|
||||
else("${def}" MATCHES ".*[*].*")
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_SKIPVARS "${def}")
|
||||
endif("${def}" MATCHES ".*[*].*")
|
||||
endfunction(autoheader_ignore_define)
|
||||
|
||||
function(autoheader_ignore_defines deflist)
|
||||
@@ -55,15 +63,22 @@ function(autoheader_ignore_defines deflist)
|
||||
endforeach(def ${${deflist}})
|
||||
endfunction(autoheader_ignore_defines)
|
||||
|
||||
function(autoheader_skip_files def)
|
||||
set_property(GLOBAL APPEND PROPERTY FILE_SKIPPATTERNS "${def}")
|
||||
endfunction(autoheader_skip_files)
|
||||
|
||||
# OS flags. For performance, put most common
|
||||
# comparisons first (that'll typicall be
|
||||
# Windows related tests)
|
||||
set(OS_FLAGS
|
||||
WIN32
|
||||
WIN32_LEAN_AND_MEAN
|
||||
_WIN32
|
||||
_WIN64
|
||||
WIN32_LEAN_AND_MEAN
|
||||
_WINDOWS
|
||||
__WIN32__
|
||||
__WIN64
|
||||
__WINDOWS__
|
||||
__APPLE__
|
||||
BSD
|
||||
CRAY1
|
||||
@@ -72,32 +87,82 @@ set(OS_FLAGS
|
||||
MSDOS
|
||||
SUNOS
|
||||
SYSV
|
||||
_AIX
|
||||
_BEOS
|
||||
_BEOS_
|
||||
_IBMR2
|
||||
_SCO_SV
|
||||
_SGI
|
||||
_ULTRIX
|
||||
_WINSOCKAPI_
|
||||
_XENIX
|
||||
__AIX
|
||||
__AIX__
|
||||
__ANDROID__
|
||||
__BEOS__
|
||||
__BeOS
|
||||
__CRAYXC
|
||||
__CRAYXE
|
||||
__CYGWIN__
|
||||
__DARWIN__
|
||||
__DOS__
|
||||
__FreeBSD__
|
||||
__GNU__
|
||||
__HAIKU__
|
||||
__LINUX__
|
||||
__MSDOS__
|
||||
__NT__
|
||||
__NetBSD
|
||||
__NetBSD__
|
||||
__OPENBSD
|
||||
__OS2__
|
||||
__OS400__
|
||||
__OpenBSD__
|
||||
__QNX__
|
||||
__SCO_VERSION__
|
||||
__TRU64__
|
||||
__aix
|
||||
__aix__
|
||||
__alpha
|
||||
__alpha__
|
||||
__apollo
|
||||
__bsdos__
|
||||
__convex__NATIVE
|
||||
__hppa
|
||||
__hpua
|
||||
__hpux
|
||||
__i386
|
||||
__i386__
|
||||
__ia64__
|
||||
__linux
|
||||
__linux__
|
||||
__minux
|
||||
__osf
|
||||
__osf__
|
||||
__ppc64__
|
||||
__ppc__
|
||||
__riscos
|
||||
__riscos__
|
||||
__sgi
|
||||
__sinix
|
||||
__sinix__
|
||||
__sp3__ # what is this? context indicates it is a platform...
|
||||
__sparc64__
|
||||
__sun
|
||||
__tru64
|
||||
__ultrix
|
||||
__ultrix__
|
||||
__x86_64__
|
||||
_sgi
|
||||
_sun
|
||||
_tru64
|
||||
convex_NATIVE
|
||||
eta10
|
||||
hpux
|
||||
ibm
|
||||
linux
|
||||
mips
|
||||
sco_sv
|
||||
sgi
|
||||
sun
|
||||
vax
|
||||
@@ -158,95 +223,111 @@ macro(header_guard rdir fname ovar)
|
||||
string(REPLACE "${rdir}/" "" stage1 ${fname})
|
||||
string(REPLACE "/" "_" stage2 ${stage1})
|
||||
string(REPLACE "." "_" stage3 ${stage2})
|
||||
string(TOUPPER "${stage3}" stage4)
|
||||
set(${ovar} ${stage4})
|
||||
string(REPLACE "-" "_" stage4 ${stage3})
|
||||
string(TOUPPER "${stage4}" stage5)
|
||||
set(${ovar} ${stage5})
|
||||
endmacro(header_guard)
|
||||
|
||||
# Given an atom from a line (i.e. one conditional if the original line had
|
||||
# and/or branches, or the original line if there were no and/or branches),
|
||||
# extract the compile flag
|
||||
macro(compile_def_flag atom ovar)
|
||||
string(REGEX REPLACE "^[ \t]*#*.*[!]*(ifdef|defined|elseif defined)[ \t]*[(]*" "" stage1 "${atom}")
|
||||
string(REGEX REPLACE "[/][*].*[*][/]" "" stage2 "${stage1}")
|
||||
string(REGEX REPLACE "[)][ \t]*" "" stage3 "${stage2}")
|
||||
string(REGEX REPLACE "[ \t]+$" "" stage4 "${stage3}")
|
||||
string(REGEX REPLACE "^[ \t]+" "" stage5 "${stage4}")
|
||||
set(${ovar} ${stage5})
|
||||
endmacro(compile_def_flag)
|
||||
|
||||
function(autoheader_scan seed_dir)
|
||||
function(autoheader_scan_internal seed_dir recurse)
|
||||
set(scan_files)
|
||||
set(extensions c h cxx cpp hxx hpp)
|
||||
get_property(C_DEFINE_SKIPVARS GLOBAL PROPERTY C_DEFINE_SKIPVARS)
|
||||
get_property(C_DEFINE_SKIPPATTERNS GLOBAL PROPERTY C_DEFINE_SKIPPATTERNS)
|
||||
get_property(FILE_SKIPPATTERNS GLOBAL PROPERTY FILE_SKIPPATTERNS)
|
||||
|
||||
foreach(exten ${extensions})
|
||||
set(sfiles)
|
||||
file(GLOB_RECURSE sfiles "${seed_dir}/*.${exten}")
|
||||
if(recurse)
|
||||
file(GLOB_RECURSE sfiles "${seed_dir}/*.${exten}")
|
||||
else(recurse)
|
||||
file(GLOB sfiles "${seed_dir}/*.${exten}")
|
||||
endif(recurse)
|
||||
set(scan_files ${scan_files} ${sfiles})
|
||||
endforeach(exten ${extensions})
|
||||
|
||||
#message("found files: ${scan_files}")
|
||||
|
||||
foreach(ptn ${FILE_SKIPPATTERNS})
|
||||
list(FILTER scan_files EXCLUDE REGEX "${ptn}")
|
||||
endforeach(ptn ${FILE_SKIPPATTERNS})
|
||||
|
||||
#message("processing files: ${scan_files}")
|
||||
|
||||
set(unique_keys)
|
||||
foreach(sf ${scan_files})
|
||||
header_guard("${seed_dir}" "${sf}" hg)
|
||||
set(SKIP_LIST ".*[ \t]+${hg}[ \t]*" ${C_DEFINE_SKIPVARS})
|
||||
file(STRINGS ${sf} SRC_LINES REGEX "^[ \t]*#.*(ifdef|defined[(]).+")
|
||||
set(def_list)
|
||||
foreach(line ${SRC_LINES})
|
||||
#message("line: ${line}")
|
||||
set(lset ${line})
|
||||
string(REPLACE "&&" ";" lset "${lset}")
|
||||
string(REPLACE "||" ";" lset "${lset}")
|
||||
foreach(l ${lset})
|
||||
#message(" atom: ${l}")
|
||||
set(skip_line 0)
|
||||
foreach(sk ${SKIP_LIST})
|
||||
if(NOT skip_line)
|
||||
#message("testing ${l} vs ${sk}")
|
||||
if("${l}" MATCHES "${sk}")
|
||||
#message("matched ${l} vs ${sk} - skipping")
|
||||
set(skip_line 1)
|
||||
endif("${l}" MATCHES "${sk}")
|
||||
endif(NOT skip_line)
|
||||
endforeach(sk ${SKIP_LIST})
|
||||
if(NOT skip_line)
|
||||
set(def_list ${def_list} ${l})
|
||||
endif(NOT skip_line)
|
||||
endforeach(l ${lset})
|
||||
endforeach(line ${SRC_LINES})
|
||||
set(SKIP_LIST "${hg}" ${C_DEFINE_SKIPVARS})
|
||||
|
||||
# Use unifdef to get the list of conditional symbols
|
||||
# See http://dotat.at/prog/unifdef/ and https://github.com/fanf2/unifdef
|
||||
execute_process(COMMAND unifdef -s ${sf} OUTPUT_VARIABLE def_list)
|
||||
string(REPLACE "\n" ";" def_list "${def_list}")
|
||||
|
||||
if(def_list)
|
||||
#message("file ${sf} def lines:")
|
||||
foreach(l ${def_list})
|
||||
set(dflag)
|
||||
compile_def_flag(${l} dflag)
|
||||
#message(" line: ${l}")
|
||||
#message(" extracted: ${dflag}")
|
||||
set(unique_keys ${unique_keys} ${dflag})
|
||||
endforeach(l ${def_list})
|
||||
foreach(dflag ${def_list})
|
||||
set(skip_flag 0)
|
||||
foreach(sk ${SKIP_LIST})
|
||||
if(NOT skip_flag)
|
||||
if("${dflag}" STREQUAL "${sk}")
|
||||
set(skip_flag 1)
|
||||
endif("${dflag}" STREQUAL "${sk}")
|
||||
endif(NOT skip_flag)
|
||||
endforeach(sk ${SKIP_LIST})
|
||||
foreach(sp ${C_DEFINE_SKIPPATTERNS})
|
||||
if(NOT skip_flag)
|
||||
if("${dflag}" MATCHES ${sp})
|
||||
set(skip_flag 1)
|
||||
endif("${dflag}" MATCHES ${sp})
|
||||
endif(NOT skip_flag)
|
||||
endforeach(sp ${C_DEFINE_SKIPPATTERNS})
|
||||
if(NOT skip_flag)
|
||||
#message(" ${dflag}")
|
||||
set(unique_keys ${unique_keys} ${dflag})
|
||||
endif(NOT skip_flag)
|
||||
endforeach(dflag ${def_list})
|
||||
endif(def_list)
|
||||
endforeach(sf ${scan_files})
|
||||
list(REMOVE_DUPLICATES unique_keys)
|
||||
foreach(k ${unique_keys})
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_VARS "${k}")
|
||||
endforeach(k ${unique_keys})
|
||||
list(LENGTH unique_keys UKLEN)
|
||||
if(UKLEN)
|
||||
list(REMOVE_DUPLICATES unique_keys)
|
||||
foreach(k ${unique_keys})
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_VARS "${k}")
|
||||
endforeach(k ${unique_keys})
|
||||
endif(UKLEN)
|
||||
|
||||
# If we've run autoheader_scan mulitple times, we need to
|
||||
# ensure uniqueness globally...
|
||||
get_property(C_DEFINE_VARS GLOBAL PROPERTY C_DEFINE_VARS)
|
||||
list(REMOVE_DUPLICATES C_DEFINE_VARS)
|
||||
list(SORT C_DEFINE_VARS)
|
||||
list(LENGTH C_DEFINE_VARS DLEN)
|
||||
if(DLEN)
|
||||
list(REMOVE_DUPLICATES C_DEFINE_VARS)
|
||||
list(SORT C_DEFINE_VARS)
|
||||
endif(DLEN)
|
||||
set_property(GLOBAL PROPERTY C_DEFINE_VARS "${C_DEFINE_VARS}")
|
||||
endfunction(autoheader_scan_internal)
|
||||
|
||||
function(autoheader_scan seed_dir)
|
||||
autoheader_scan_internal("${seed_dir}" 0)
|
||||
endfunction(autoheader_scan)
|
||||
|
||||
function(autoheader_recursive_scan seed_dir)
|
||||
autoheader_scan_internal("${seed_dir}" 1)
|
||||
endfunction(autoheader_recursive_scan)
|
||||
|
||||
|
||||
# For testing convenience, the following will exercise the
|
||||
# logic in cmake -P script mode. Should be removed if/when
|
||||
# this goes "live" in the real build.
|
||||
|
||||
set(LOCAL_SKIP DIRENT_ BRLCADBUILD BRLCAD_ DM_ FB_ NO_BOMBING_MACROS USE_BINARY_ATTRIBUTES
|
||||
set(LOCAL_SKIP DIRENT_ BRLCADBUILD ^BRLCAD_* ^DM_* ^FB_* NO_BOMBING_MACROS USE_BINARY_ATTRIBUTES
|
||||
IF_WGL IF_X IF_QT IF_OGL NO_DEBUG_CHECKING USE_OPENCL)
|
||||
autoheader_ignore_defines(LOCAL_SKIP)
|
||||
|
||||
set_property(GLOBAL APPEND PROPERTY C_DEFINE_SKIPVARS ".*IMPORT.*")
|
||||
autoheader_scan(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
autoheader_scan(${CMAKE_CURRENT_SOURCE_DIR}/src/libbu)
|
||||
autoheader_skip_files(".*src/other/.*")
|
||||
|
||||
autoheader_recursive_scan(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
autoheader_recursive_scan(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
autoheader_scan(${CMAKE_CURRENT_SOURCE_DIR}/misc/tools/perplex)
|
||||
|
||||
get_property(C_DEFINE_VARS GLOBAL PROPERTY C_DEFINE_VARS)
|
||||
message("keys:")
|
||||
|
||||
@@ -80,6 +80,7 @@ set(misc_ignore_files
|
||||
mime.types
|
||||
mime_cad.types
|
||||
nsis
|
||||
osl_shaders
|
||||
wix
|
||||
svn2git
|
||||
uncpowerplant2g.sh
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
SET(re2c_ignore_files
|
||||
CHANGELOG
|
||||
CMake
|
||||
README.in
|
||||
basics.h
|
||||
@@ -9,23 +8,17 @@ config.h.in
|
||||
config_w32.h.in
|
||||
configure.in
|
||||
dfa.h
|
||||
doc
|
||||
examples
|
||||
globals.h
|
||||
htdocs
|
||||
ins.h
|
||||
lessons
|
||||
mbo_getopt.h
|
||||
re2c_parser.h
|
||||
parser.yy
|
||||
re.h
|
||||
re2c.1.in
|
||||
re2c.spec.in
|
||||
run_tests.sh.in
|
||||
scanner.h
|
||||
scanner.re
|
||||
stream_lc.h
|
||||
substr.h
|
||||
test
|
||||
token.h
|
||||
)
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
Version 0.13.6 (2008-??-??)
|
||||
---------------------------
|
||||
|
||||
Version 0.13.5 (2008-05-25)
|
||||
---------------------------
|
||||
- Fixed #1952896 Segfault in re2c::Scanner::scan.
|
||||
- Fixed #1952842 Regression.
|
||||
|
||||
Version 0.13.4 (2008-04-05)
|
||||
---------------------------
|
||||
- Added transparent handling of #line directives in input files.
|
||||
- Added re2c:yyfill:check inplace configuration.
|
||||
- Added re2c:define:YYSETSTATE:naked inplace configuration.
|
||||
- Added re2c:flags:w and re2c:flags:u inplace configurations.
|
||||
- Added the ability to add rules in 'use:re2c' blocks.
|
||||
- Changed -r flag to accept only 'rules:re2c' and 'use:re2c' blocks.
|
||||
|
||||
Version 0.13.3 (2008-03-14)
|
||||
---------------------------
|
||||
- Added -r flag to allow reuse of scanner definitions.
|
||||
- Added -F flag to support flex syntax in rules.
|
||||
- Fixed SEGV in scanner that occurs with very large blocks.
|
||||
- Fixed issue with unused yybm.
|
||||
- Partial support for flex syntax.
|
||||
- Changed to allow /* comments with -c switch.
|
||||
- Added flag -D/--emit-dot.
|
||||
|
||||
Version 0.13.2 (2008-02-14)
|
||||
---------------------------
|
||||
- Added flag --case-inverted.
|
||||
- Added flag --case-insensitive.
|
||||
- Added support for '<!...>' to enable rule setup.
|
||||
- Added support for '=>' style rules.
|
||||
- Added support for ':=' style rules.
|
||||
- Added support for ':=>' style rules.
|
||||
- Added re2c:cond:divider and re2c:con:goto inplace configuration.
|
||||
- Fixed code generation to emit space after 'if'.
|
||||
|
||||
Version 0.13.1 (2007-08-24)
|
||||
---------------------------
|
||||
- Added custom build rules for Visual Studio 2005 (re2c.rules). (William Swanson)
|
||||
- Fixed issue with some compilers.
|
||||
- Fixed #1776177 Build on AIX.
|
||||
- Fixed #1743180 fwrite with 0 length crashes on OS X.
|
||||
|
||||
Version 0.13.0 (2007-06-24)
|
||||
---------------------------
|
||||
- Added -c and -t to generate scanners with (f)lex-like condition support.
|
||||
- Fixed issue with short form of switches and parameter if not first switch.
|
||||
- Fixed #1708378 segfault in actions.cc.
|
||||
|
||||
Version 0.12.3 (2007-08-24)
|
||||
---------------------------
|
||||
- Fixed issue with some compilers.
|
||||
- Fixed #1776177 Build on AIX.
|
||||
- Fixed #1743180 fwrite with 0 length crashes on OS X.
|
||||
|
||||
Version 0.12.2 (2007-06-26)
|
||||
---------------------------
|
||||
- Fixed #1743180 fwrite with 0 length crashes on OS X.
|
||||
|
||||
Version 0.12.1 (2007-05-23)
|
||||
---------------------------
|
||||
- Fixed #1711240 problem with '"' and 7F on EBCDIC platforms.
|
||||
|
||||
Version 0.12.0 (2007-05-01)
|
||||
---------------------------
|
||||
- Re-release of 0.11.3 as new stable branch.
|
||||
- Fixed issue with short form of switches and parameter if not first switch.
|
||||
- Fixed #1708378 segfault in actions.cc.
|
||||
|
||||
Version 0.11.3 (2007-04-01)
|
||||
---------------------------
|
||||
- Added support for underscores in named definitions.
|
||||
- Added new option --no-generation-date.
|
||||
- Fixed issue with long form of switches.
|
||||
|
||||
Version 0.11.2 (2007-03-01)
|
||||
---------------------------
|
||||
- Added inplace configuration 're2c:yyfill:parameter'.
|
||||
- Added inplace configuration 're2c:yych:conversion'.
|
||||
- Fixed -u switch code generation.
|
||||
- Added ability to avoid defines and overwrite variable and label names.
|
||||
|
||||
Version 0.11.1 (2007-02-20)
|
||||
---------------------------
|
||||
- Applied #1647875 add const to yybm vector.
|
||||
|
||||
Version 0.11.0 (2007-01-01)
|
||||
---------------------------
|
||||
- Added -u switch to support unicode.
|
||||
|
||||
Version 0.10.8 (2007-04-01)
|
||||
---------------------------
|
||||
- Fixed issue with long form of switches.
|
||||
|
||||
Version 0.10.7 (2007-02-20)
|
||||
---------------------------
|
||||
- Applied #1647875 add const to yybm vector.
|
||||
|
||||
Version 0.10.6 (2006-08-05)
|
||||
---------------------------
|
||||
- Fixed #1529351 Segv bug on unterminated code blocks.
|
||||
- Fixed #1528269 Invalid code generation.
|
||||
|
||||
Version 0.10.5 (2006-06-11)
|
||||
---------------------------
|
||||
- Fixed long form of -1 switch to --single-pass as noted in man page and help.
|
||||
- Added MSVC 2003 project files and renamed old 2002 ones.
|
||||
|
||||
Version 0.10.4 (2006-06-01)
|
||||
---------------------------
|
||||
- Fix whitespace in generated code.
|
||||
|
||||
Version 0.10.3 (2006-05-14)
|
||||
---------------------------
|
||||
- Fixed issue with -wb and -ws.
|
||||
- Added -g switch to support gcc's computed goto's.
|
||||
- Changed to use nested if's instead of "switch(yyaccept)" in -s mode.
|
||||
|
||||
Version 0.10.2 (2006-05-01)
|
||||
---------------------------
|
||||
- Changed to generate YYMARKER only when needed or in single pass mode.
|
||||
- Added -1 switch to force single pass generation and make two pass the default.
|
||||
- Fixed -i switch.
|
||||
- Added configuration 'yyfill:enable' to allow suppression of YYFILL() blocks.
|
||||
- Added tutorial like lessons to re2c.
|
||||
- Added /*!ignore:re2c */ to support documenting of re2c source.
|
||||
- Fixed issue with multiline re2c comments (/*!max:re2c ... */ and alike).
|
||||
- Fixed generation of YYDEBUG() when using -d switch.
|
||||
- Added /*!getstate:re2c */ which triggers generation of the YYGETSTATE() block.
|
||||
- Added configuration 'state:abort'.
|
||||
- Changed to not generate yyNext unless configuration 'state:nextlabel' is used.
|
||||
- Changed to not generate yyaccept code unless needed.
|
||||
- Changed to use if- instead of switch-expression when yyaccpt has only one case.
|
||||
- Added docu, examples and tests to .src.zip package (0.10.1 zip was repackaged).
|
||||
- Fixed #1479044 incorrect code generated when using -b.
|
||||
- Fixed #1472770 re2c creates an infinite loop.
|
||||
- Fixed #1454253 Piece of code saving a backtracking point not generated.
|
||||
- Fixed #1463639 Missing forward declaration.
|
||||
- Implemented #1187127 savable state support for multiple re2c blocks.
|
||||
|
||||
Version 0.10.1 (2006-02-28)
|
||||
---------------------------
|
||||
- Added support for Solaris and native SUN compiler.
|
||||
- Applied #1438160 expose YYCTXMARKER.
|
||||
|
||||
Version 0.10.0 (2006-02-18)
|
||||
---------------------------
|
||||
- Added make target zip to create windows source packages as zip files.
|
||||
- Added re2c:startlabel configuration.
|
||||
- Fixed code generation to not generate unreachable code for initial state.
|
||||
- Added support for c/c++ compatible \u and \U unicode notation.
|
||||
- Added ability to control indentation.
|
||||
- Made scanner error out in case an ambiguous /* is found.
|
||||
- Fixed indentation of generated code.
|
||||
- Added support for DOS line endings.
|
||||
- Added experimental unicode support.
|
||||
- Added config_w32.h to build out of the box on windows (using msvc 2002+).
|
||||
- Added Microsoft Visual C .NET 2005 build files.
|
||||
- Applied #1411087 variable length trailing context.
|
||||
- Applied #1408326 do not generate goto next state.
|
||||
- Applied #1408282 CharSet initialization fix.
|
||||
- Applied #1408278 readsome with MSVC.
|
||||
- Applied #1307467 Unicode patch for 0.9.7.
|
||||
|
||||
Version 0.9.12 (2005-12-28)
|
||||
---------------------------
|
||||
- Fixed bug #1390174 re2c cannot accept {0,}.
|
||||
|
||||
Version 0.9.11 (2005-12-18)
|
||||
---------------------------
|
||||
- Fixed #1313083 -e (EBCDIC cross compile) broken.
|
||||
- Fixed #1297658 underestimation of n in YYFILL(n).
|
||||
- Applied #1339483 Avoid rebuilds of re2c when running subtargets.
|
||||
- Implemented #1335305 symbol table reimplementation, just slightly modified.
|
||||
|
||||
Version 0.9.10 (2005-09-04)
|
||||
---------------------------
|
||||
- Added -i switch to avoid generating #line information.
|
||||
- Fixed bug #1251653 re2c generate some invalid #line on WIN32.
|
||||
|
||||
Version 0.9.9 (2005-07-21)
|
||||
--------------------------
|
||||
- Implemented #1232777 negated char classes '[^...]' and the dot operator '.'.
|
||||
- Added hexadecimal character definitions.
|
||||
- Added consistency check for octal character definitions.
|
||||
|
||||
Version 0.9.8 (2005-06-26)
|
||||
--------------------------
|
||||
- Fixed code generation for -b switch.
|
||||
- Added Microsoft Visual C .NET build files.
|
||||
|
||||
Version 0.9.7 (2005-04-30)
|
||||
--------------------------
|
||||
- Applied #1181535 storable state patch.
|
||||
- Added -d flag which outputs a debuggable parser.
|
||||
- Fixed generation of '#line' directives (according to ISO-C99).
|
||||
- Fixed bug #1187785 Re2c fails to generate valid code.
|
||||
- Fixed bug #1187452 unused variable `yyaccept'.
|
||||
|
||||
Version 0.9.6 (2005-04-14)
|
||||
--------------------------
|
||||
- Fixed build with gcc >= 3.4.
|
||||
|
||||
Version 0.9.5 (2005-04-08)
|
||||
--------------------------
|
||||
- Added /*!max:re2c */ which emits a '#define YYMAXFILL <max>\n' line
|
||||
This allows to define buffers of the minimum required length. Occurrence
|
||||
must follow '/*re2c */ and cannot precede it.
|
||||
- Changed re2c to two pass generation to output warning free code.
|
||||
- Fixed bug #1163046 re2c hangs when processing valid re-file.
|
||||
- Fixed bug #1022799 re2c scanner has buffering bug.
|
||||
|
||||
Version 0.9.4 (2005-03-12)
|
||||
--------------------------
|
||||
- Added --vernum support.
|
||||
- Fixed bug #1054496 incorrect code generated with -b option.
|
||||
- Fixed bug #1012748 re2c does not emit last line if '\n' missing.
|
||||
- Fixed bug #999104 --output=output option does not work as documented.
|
||||
- Fixed bug #999103 Invalid options prefixed with two dashes cause program crash.
|
||||
|
||||
Version 0.9.3 (2004-05-26)
|
||||
--------------------------
|
||||
- Fixes one small possible bug in the generated output. ych instead of yych is
|
||||
output in certain circumstances
|
||||
|
||||
Version 0.9.2 (2004-05-26)
|
||||
--------------------------
|
||||
- Added -o option to specify the output file which also will set the #line
|
||||
directives to something useful.
|
||||
- Print version to cout instead cerr.
|
||||
- Added -h and -- style options.
|
||||
- Moved development to http://sourceforge.net/projects/re2c .
|
||||
- Fixed bug #960144 minor cosmetic problem.
|
||||
- Fixed bug #953181 cannot compile with.
|
||||
- Fixed bug #939277 Windows support.
|
||||
- Fixed bug #914462 automake build patch
|
||||
- Fixed bug #891940 braced quantifiers: {\d+(,|,\d+)?} style.
|
||||
- Fixed bug #869298 Add case insensitive string literals.
|
||||
- Fixed bug #869297 Input buffer overrun.
|
||||
|
||||
Version 0.9.1 (2003-12-13)
|
||||
--------------------------
|
||||
- Removed rcs comments in source files.
|
||||
|
||||
Version 0.9
|
||||
-----------
|
||||
- Redistribution based on version 0.5.
|
||||
- Added parentheses to assignment expressions in 'if' statements.
|
||||
- Rearranged class members to match initialization order.
|
||||
- Substr fix.
|
||||
- Use array delete [] when necessary.
|
||||
- Other minor fixes for subduing compiler warnings.
|
||||
|
||||
@@ -134,7 +134,6 @@ if(NOT RE2C_SKIP_INSTALL)
|
||||
endif(NOT RE2C_SKIP_INSTALL)
|
||||
|
||||
configure_file(README.in ${CMAKE_CURRENT_BINARY_DIR}/README)
|
||||
configure_file(run_tests.sh.in ${CMAKE_CURRENT_BINARY_DIR}/run_tests.sh @ONLY)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,48 +0,0 @@
|
||||
@Article{Bumbulis94,
|
||||
author = {Peter Bumbulis and Donald D. Cowan},
|
||||
title = {RE2C -- A More Versatile Scanner Generator},
|
||||
journal = "ACM Letters on Programming Languages and Systems",
|
||||
volume = 2,
|
||||
number = "1--4",
|
||||
year = 1994,
|
||||
abstract = {
|
||||
It is usually claimed that lexical analysis routines are still coded by
|
||||
hand, despite the widespread availability of scanner generators, for
|
||||
efficiency reasons. While efficiency is a consideration, there exist
|
||||
freely available scanner generators such as GLA \cite{Gray88} that can
|
||||
generate scanners that are faster than most hand-coded ones. However,
|
||||
most generated scanners are tailored for a particular environment, and
|
||||
retargetting these scanners to other environments, if possible, is
|
||||
usually complex enough to make a hand-coded scanner more appealing. In
|
||||
this paper we describe RE2C, a scanner generator that not only generates
|
||||
scanners which are faster (and usually smaller) than those produced by
|
||||
any other scanner generator known to the authors, including GLA, but
|
||||
also adapt easily to any environment.
|
||||
}
|
||||
}
|
||||
@Article{Gray88,
|
||||
author = {Robert W. Gray},
|
||||
title = {{$\gamma$-GLA} - {A} Generator for Lexical Analyzers That
|
||||
Programmers Can Use},
|
||||
journal = {USENIX Conference Proceedings},
|
||||
year = {1988},
|
||||
month = {June},
|
||||
pages = {147-160},
|
||||
abstract = {Writing an efficient lexical analyzer for even a simple
|
||||
language is not a trivial task, and should not be done by hand. We
|
||||
describe GLA, a tool that generates very efficient scanners. These
|
||||
scanners do not use the conventional transition matrix, but instead
|
||||
use a few 128 element vectors. Scanning time is only slightly
|
||||
greater than the absolute minimum --- the time it takes to look at
|
||||
each character in a file. The GLA language allows simple, concise
|
||||
specification of scanners. Augmenting regular expressions with
|
||||
auxiliary scanners easily handles nasty problems such as C comments
|
||||
and C literal constants. We formalize the connection between token
|
||||
scanning and token processing by associating a processor with
|
||||
appropriate patterns. A library of canned descriptions simplifies the
|
||||
specification of commonly used language pieces --- such as,
|
||||
C\_IDENTIFIERS, C\_STRINGS, PASCAL\_COMMENTS, etc. Finally, carefully
|
||||
tuned lexical analysis support modules are provided for error
|
||||
handling, input buffering, storing identifiers in hash tables and
|
||||
manipulating denotations.}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MAP_NORESERVE
|
||||
#define MAP_NORESERVE 0
|
||||
#endif
|
||||
|
||||
volatile char ch;
|
||||
|
||||
main(){
|
||||
struct stat statbuf;
|
||||
uchar *buf;
|
||||
fstat(0, &statbuf);
|
||||
buf = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED|MAP_NORESERVE,
|
||||
0, 0);
|
||||
if(buf != (uchar*)(-1)){
|
||||
uchar *cur, *lim = &buf[statbuf.st_size];
|
||||
for(cur = buf; buf != lim; ++cur){
|
||||
ch = *cur;
|
||||
}
|
||||
munmap(buf, statbuf.st_size);
|
||||
}
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ADDEQ 257
|
||||
#define ANDAND 258
|
||||
#define ANDEQ 259
|
||||
#define ARRAY 260
|
||||
#define ASM 261
|
||||
#define AUTO 262
|
||||
#define BREAK 263
|
||||
#define CASE 264
|
||||
#define CHAR 265
|
||||
#define CONST 266
|
||||
#define CONTINUE 267
|
||||
#define DECR 268
|
||||
#define DEFAULT 269
|
||||
#define DEREF 270
|
||||
#define DIVEQ 271
|
||||
#define DO 272
|
||||
#define DOUBLE 273
|
||||
#define ELLIPSIS 274
|
||||
#define ELSE 275
|
||||
#define ENUM 276
|
||||
#define EQL 277
|
||||
#define EXTERN 278
|
||||
#define FCON 279
|
||||
#define FLOAT 280
|
||||
#define FOR 281
|
||||
#define FUNCTION 282
|
||||
#define GEQ 283
|
||||
#define GOTO 284
|
||||
#define ICON 285
|
||||
#define ID 286
|
||||
#define IF 287
|
||||
#define INCR 288
|
||||
#define INT 289
|
||||
#define LEQ 290
|
||||
#define LONG 291
|
||||
#define LSHIFT 292
|
||||
#define LSHIFTEQ 293
|
||||
#define MODEQ 294
|
||||
#define MULEQ 295
|
||||
#define NEQ 296
|
||||
#define OREQ 297
|
||||
#define OROR 298
|
||||
#define POINTER 299
|
||||
#define REGISTER 300
|
||||
#define RETURN 301
|
||||
#define RSHIFT 302
|
||||
#define RSHIFTEQ 303
|
||||
#define SCON 304
|
||||
#define SHORT 305
|
||||
#define SIGNED 306
|
||||
#define SIZEOF 307
|
||||
#define STATIC 308
|
||||
#define STRUCT 309
|
||||
#define SUBEQ 310
|
||||
#define SWITCH 311
|
||||
#define TYPEDEF 312
|
||||
#define UNION 313
|
||||
#define UNSIGNED 314
|
||||
#define VOID 315
|
||||
#define VOLATILE 316
|
||||
#define WHILE 317
|
||||
#define XOREQ 318
|
||||
#define EOI 319
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#define BSIZE 8192
|
||||
|
||||
#define YYCTYPE uchar
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT s->lim
|
||||
#define YYMARKER s->ptr
|
||||
#define YYFILL(n) {cursor = fill(s, cursor);}
|
||||
|
||||
#define RET(i) {s->cur = cursor; return i;}
|
||||
|
||||
typedef struct Scanner {
|
||||
int fd;
|
||||
uchar *bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof;
|
||||
uint line;
|
||||
} Scanner;
|
||||
|
||||
uchar *fill(Scanner *s, uchar *cursor){
|
||||
if(!s->eof) {
|
||||
uint cnt = s->tok - s->bot;
|
||||
if(cnt){
|
||||
memcpy(s->bot, s->tok, s->lim - s->tok);
|
||||
s->tok = s->bot;
|
||||
s->ptr -= cnt;
|
||||
cursor -= cnt;
|
||||
s->pos -= cnt;
|
||||
s->lim -= cnt;
|
||||
}
|
||||
if((s->top - s->lim) < BSIZE){
|
||||
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
|
||||
memcpy(buf, s->tok, s->lim - s->tok);
|
||||
s->tok = buf;
|
||||
s->ptr = &buf[s->ptr - s->bot];
|
||||
cursor = &buf[cursor - s->bot];
|
||||
s->pos = &buf[s->pos - s->bot];
|
||||
s->lim = &buf[s->lim - s->bot];
|
||||
s->top = &s->lim[BSIZE];
|
||||
free(s->bot);
|
||||
s->bot = buf;
|
||||
}
|
||||
if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
|
||||
s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
|
||||
}
|
||||
s->lim += cnt;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int scan(Scanner *s){
|
||||
uchar *cursor = s->cur;
|
||||
std:
|
||||
s->tok = cursor;
|
||||
/*!re2c
|
||||
any = [\000-\377];
|
||||
O = [0-7];
|
||||
D = [0-9];
|
||||
L = [a-zA-Z_];
|
||||
H = [a-fA-F0-9];
|
||||
E = [Ee] [+-]? D+;
|
||||
FS = [fFlL];
|
||||
IS = [uUlL]*;
|
||||
ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
|
||||
*/
|
||||
|
||||
/*!re2c
|
||||
"/*" { goto comment; }
|
||||
|
||||
"auto" { RET(AUTO); }
|
||||
"break" { RET(BREAK); }
|
||||
"case" { RET(CASE); }
|
||||
"char" { RET(CHAR); }
|
||||
"const" { RET(CONST); }
|
||||
"continue" { RET(CONTINUE); }
|
||||
"default" { RET(DEFAULT); }
|
||||
"do" { RET(DO); }
|
||||
"double" { RET(DOUBLE); }
|
||||
"else" { RET(ELSE); }
|
||||
"enum" { RET(ENUM); }
|
||||
"extern" { RET(EXTERN); }
|
||||
"float" { RET(FLOAT); }
|
||||
"for" { RET(FOR); }
|
||||
"goto" { RET(GOTO); }
|
||||
"if" { RET(IF); }
|
||||
"int" { RET(INT); }
|
||||
"long" { RET(LONG); }
|
||||
"register" { RET(REGISTER); }
|
||||
"return" { RET(RETURN); }
|
||||
"short" { RET(SHORT); }
|
||||
"signed" { RET(SIGNED); }
|
||||
"sizeof" { RET(SIZEOF); }
|
||||
"static" { RET(STATIC); }
|
||||
"struct" { RET(STRUCT); }
|
||||
"switch" { RET(SWITCH); }
|
||||
"typedef" { RET(TYPEDEF); }
|
||||
"union" { RET(UNION); }
|
||||
"unsigned" { RET(UNSIGNED); }
|
||||
"void" { RET(VOID); }
|
||||
"volatile" { RET(VOLATILE); }
|
||||
"while" { RET(WHILE); }
|
||||
|
||||
L (L|D)* { RET(ID); }
|
||||
|
||||
("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
|
||||
(['] (ESC|any\[\n\\'])* ['])
|
||||
{ RET(ICON); }
|
||||
|
||||
(D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?)
|
||||
{ RET(FCON); }
|
||||
|
||||
(["] (ESC|any\[\n\\"])* ["])
|
||||
{ RET(SCON); }
|
||||
|
||||
"..." { RET(ELLIPSIS); }
|
||||
">>=" { RET(RSHIFTEQ); }
|
||||
"<<=" { RET(LSHIFTEQ); }
|
||||
"+=" { RET(ADDEQ); }
|
||||
"-=" { RET(SUBEQ); }
|
||||
"*=" { RET(MULEQ); }
|
||||
"/=" { RET(DIVEQ); }
|
||||
"%=" { RET(MODEQ); }
|
||||
"&=" { RET(ANDEQ); }
|
||||
"^=" { RET(XOREQ); }
|
||||
"|=" { RET(OREQ); }
|
||||
">>" { RET(RSHIFT); }
|
||||
"<<" { RET(LSHIFT); }
|
||||
"++" { RET(INCR); }
|
||||
"--" { RET(DECR); }
|
||||
"->" { RET(DEREF); }
|
||||
"&&" { RET(ANDAND); }
|
||||
"||" { RET(OROR); }
|
||||
"<=" { RET(LEQ); }
|
||||
">=" { RET(GEQ); }
|
||||
"==" { RET(EQL); }
|
||||
"!=" { RET(NEQ); }
|
||||
";" { RET(';'); }
|
||||
"{" { RET('{'); }
|
||||
"}" { RET('}'); }
|
||||
"," { RET(','); }
|
||||
":" { RET(':'); }
|
||||
"=" { RET('='); }
|
||||
"(" { RET('('); }
|
||||
")" { RET(')'); }
|
||||
"[" { RET('['); }
|
||||
"]" { RET(']'); }
|
||||
"." { RET('.'); }
|
||||
"&" { RET('&'); }
|
||||
"!" { RET('!'); }
|
||||
"~" { RET('~'); }
|
||||
"-" { RET('-'); }
|
||||
"+" { RET('+'); }
|
||||
"*" { RET('*'); }
|
||||
"/" { RET('/'); }
|
||||
"%" { RET('%'); }
|
||||
"<" { RET('<'); }
|
||||
">" { RET('>'); }
|
||||
"^" { RET('^'); }
|
||||
"|" { RET('|'); }
|
||||
"?" { RET('?'); }
|
||||
|
||||
|
||||
[ \t\v\f]+ { goto std; }
|
||||
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->pos = cursor; s->line++;
|
||||
goto std;
|
||||
}
|
||||
|
||||
any
|
||||
{
|
||||
printf("unexpected character: %c\n", *s->tok);
|
||||
goto std;
|
||||
}
|
||||
*/
|
||||
|
||||
comment:
|
||||
/*!re2c
|
||||
"*/" { goto std; }
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->tok = s->pos = cursor; s->line++;
|
||||
goto comment;
|
||||
}
|
||||
any { goto comment; }
|
||||
*/
|
||||
}
|
||||
|
||||
main(){
|
||||
Scanner in;
|
||||
int t;
|
||||
memset((char*) &in, 0, sizeof(in));
|
||||
in.fd = 0;
|
||||
while((t = scan(&in)) != EOI){
|
||||
/*
|
||||
printf("%d\t%.*s\n", t, in.cur - in.tok, in.tok);
|
||||
printf("%d\n", t);
|
||||
*/
|
||||
}
|
||||
close(in.fd);
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ADDEQ 257
|
||||
#define ANDAND 258
|
||||
#define ANDEQ 259
|
||||
#define ARRAY 260
|
||||
#define ASM 261
|
||||
#define AUTO 262
|
||||
#define BREAK 263
|
||||
#define CASE 264
|
||||
#define CHAR 265
|
||||
#define CONST 266
|
||||
#define CONTINUE 267
|
||||
#define DECR 268
|
||||
#define DEFAULT 269
|
||||
#define DEREF 270
|
||||
#define DIVEQ 271
|
||||
#define DO 272
|
||||
#define DOUBLE 273
|
||||
#define ELLIPSIS 274
|
||||
#define ELSE 275
|
||||
#define ENUM 276
|
||||
#define EQL 277
|
||||
#define EXTERN 278
|
||||
#define FCON 279
|
||||
#define FLOAT 280
|
||||
#define FOR 281
|
||||
#define FUNCTION 282
|
||||
#define GEQ 283
|
||||
#define GOTO 284
|
||||
#define ICON 285
|
||||
#define ID 286
|
||||
#define IF 287
|
||||
#define INCR 288
|
||||
#define INT 289
|
||||
#define LEQ 290
|
||||
#define LONG 291
|
||||
#define LSHIFT 292
|
||||
#define LSHIFTEQ 293
|
||||
#define MODEQ 294
|
||||
#define MULEQ 295
|
||||
#define NEQ 296
|
||||
#define OREQ 297
|
||||
#define OROR 298
|
||||
#define POINTER 299
|
||||
#define REGISTER 300
|
||||
#define RETURN 301
|
||||
#define RSHIFT 302
|
||||
#define RSHIFTEQ 303
|
||||
#define SCON 304
|
||||
#define SHORT 305
|
||||
#define SIGNED 306
|
||||
#define SIZEOF 307
|
||||
#define STATIC 308
|
||||
#define STRUCT 309
|
||||
#define SUBEQ 310
|
||||
#define SWITCH 311
|
||||
#define TYPEDEF 312
|
||||
#define UNION 313
|
||||
#define UNSIGNED 314
|
||||
#define VOID 315
|
||||
#define VOLATILE 316
|
||||
#define WHILE 317
|
||||
#define XOREQ 318
|
||||
#define EOI 319
|
||||
|
||||
typedef unsigned int unint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#define YYCTYPE uchar
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT s->lim
|
||||
#define YYMARKER s->ptr
|
||||
#define YYFILL(n) {cursor = fill(s, cursor);}
|
||||
|
||||
#define RET(i) {s->cur = cursor; return i;}
|
||||
|
||||
typedef struct Scanner {
|
||||
uchar *tok, *ptr, *cur, *pos, *lim, *eof;
|
||||
unint line;
|
||||
} Scanner;
|
||||
|
||||
uchar *fill(Scanner *s, uchar *cursor){
|
||||
if(!s->eof){
|
||||
unint cnt = s->lim - s->tok;
|
||||
uchar *buf = malloc((cnt + 1)*sizeof(uchar));
|
||||
memcpy(buf, s->tok, cnt);
|
||||
cursor = &buf[cursor - s->tok];
|
||||
s->pos = &buf[s->pos - s->tok];
|
||||
s->ptr = &buf[s->ptr - s->tok];
|
||||
s->lim = &buf[cnt];
|
||||
s->eof = s->lim; *(s->eof)++ = '\n';
|
||||
s->tok = buf;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int scan(Scanner *s){
|
||||
uchar *cursor = s->cur;
|
||||
std:
|
||||
s->tok = cursor;
|
||||
/*!re2c
|
||||
any = [\000-\377];
|
||||
O = [0-7];
|
||||
D = [0-9];
|
||||
L = [a-zA-Z_];
|
||||
H = [a-fA-F0-9];
|
||||
E = [Ee] [+-]? D+;
|
||||
FS = [fFlL];
|
||||
IS = [uUlL]*;
|
||||
ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
|
||||
*/
|
||||
|
||||
/*!re2c
|
||||
"/*" { goto comment; }
|
||||
|
||||
"auto" { RET(AUTO); }
|
||||
"break" { RET(BREAK); }
|
||||
"case" { RET(CASE); }
|
||||
"char" { RET(CHAR); }
|
||||
"const" { RET(CONST); }
|
||||
"continue" { RET(CONTINUE); }
|
||||
"default" { RET(DEFAULT); }
|
||||
"do" { RET(DO); }
|
||||
"double" { RET(DOUBLE); }
|
||||
"else" { RET(ELSE); }
|
||||
"enum" { RET(ENUM); }
|
||||
"extern" { RET(EXTERN); }
|
||||
"float" { RET(FLOAT); }
|
||||
"for" { RET(FOR); }
|
||||
"goto" { RET(GOTO); }
|
||||
"if" { RET(IF); }
|
||||
"int" { RET(INT); }
|
||||
"long" { RET(LONG); }
|
||||
"register" { RET(REGISTER); }
|
||||
"return" { RET(RETURN); }
|
||||
"short" { RET(SHORT); }
|
||||
"signed" { RET(SIGNED); }
|
||||
"sizeof" { RET(SIZEOF); }
|
||||
"static" { RET(STATIC); }
|
||||
"struct" { RET(STRUCT); }
|
||||
"switch" { RET(SWITCH); }
|
||||
"typedef" { RET(TYPEDEF); }
|
||||
"union" { RET(UNION); }
|
||||
"unsigned" { RET(UNSIGNED); }
|
||||
"void" { RET(VOID); }
|
||||
"volatile" { RET(VOLATILE); }
|
||||
"while" { RET(WHILE); }
|
||||
|
||||
L (L|D)* { RET(ID); }
|
||||
|
||||
("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
|
||||
(['] (ESC|any\[\n\\'])* ['])
|
||||
{ RET(ICON); }
|
||||
|
||||
(D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?)
|
||||
{ RET(FCON); }
|
||||
|
||||
(["] (ESC|any\[\n\\"])* ["])
|
||||
{ RET(SCON); }
|
||||
|
||||
"..." { RET(ELLIPSIS); }
|
||||
">>=" { RET(RSHIFTEQ); }
|
||||
"<<=" { RET(LSHIFTEQ); }
|
||||
"+=" { RET(ADDEQ); }
|
||||
"-=" { RET(SUBEQ); }
|
||||
"*=" { RET(MULEQ); }
|
||||
"/=" { RET(DIVEQ); }
|
||||
"%=" { RET(MODEQ); }
|
||||
"&=" { RET(ANDEQ); }
|
||||
"^=" { RET(XOREQ); }
|
||||
"|=" { RET(OREQ); }
|
||||
">>" { RET(RSHIFT); }
|
||||
"<<" { RET(LSHIFT); }
|
||||
"++" { RET(INCR); }
|
||||
"--" { RET(DECR); }
|
||||
"->" { RET(DEREF); }
|
||||
"&&" { RET(ANDAND); }
|
||||
"||" { RET(OROR); }
|
||||
"<=" { RET(LEQ); }
|
||||
">=" { RET(GEQ); }
|
||||
"==" { RET(EQL); }
|
||||
"!=" { RET(NEQ); }
|
||||
";" { RET(';'); }
|
||||
"{" { RET('{'); }
|
||||
"}" { RET('}'); }
|
||||
"," { RET(','); }
|
||||
":" { RET(':'); }
|
||||
"=" { RET('='); }
|
||||
"(" { RET('('); }
|
||||
")" { RET(')'); }
|
||||
"[" { RET('['); }
|
||||
"]" { RET(']'); }
|
||||
"." { RET('.'); }
|
||||
"&" { RET('&'); }
|
||||
"!" { RET('!'); }
|
||||
"~" { RET('~'); }
|
||||
"-" { RET('-'); }
|
||||
"+" { RET('+'); }
|
||||
"*" { RET('*'); }
|
||||
"/" { RET('/'); }
|
||||
"%" { RET('%'); }
|
||||
"<" { RET('<'); }
|
||||
">" { RET('>'); }
|
||||
"^" { RET('^'); }
|
||||
"|" { RET('|'); }
|
||||
"?" { RET('?'); }
|
||||
|
||||
|
||||
[ \t\v\f]+ { goto std; }
|
||||
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->pos = cursor; s->line++;
|
||||
goto std;
|
||||
}
|
||||
|
||||
any
|
||||
{
|
||||
printf("unexpected character: %c\n", *s->tok);
|
||||
goto std;
|
||||
}
|
||||
*/
|
||||
|
||||
comment:
|
||||
/*!re2c
|
||||
"*/" { goto std; }
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->tok = s->pos = cursor; s->line++;
|
||||
goto comment;
|
||||
}
|
||||
any { goto comment; }
|
||||
*/
|
||||
}
|
||||
|
||||
#ifndef MAP_NORESERVE
|
||||
#define MAP_NORESERVE 0
|
||||
#endif
|
||||
|
||||
main(){
|
||||
Scanner in;
|
||||
struct stat statbuf;
|
||||
uchar *buf;
|
||||
fstat(0, &statbuf);
|
||||
buf = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED|MAP_NORESERVE,
|
||||
0, 0);
|
||||
if(buf != (uchar*)(-1)){
|
||||
int t;
|
||||
in.lim = &(in.cur = buf)[statbuf.st_size];
|
||||
in.pos = NULL;
|
||||
in.eof = NULL;
|
||||
while((t = scan(&in)) != EOI){
|
||||
/*
|
||||
printf("%d\t%.*s\n", t, in.cur - in.tok, in.tok);
|
||||
printf("%d\n", t);
|
||||
*/
|
||||
}
|
||||
munmap(buf, statbuf.st_size);
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ADDEQ 257
|
||||
#define ANDAND 258
|
||||
#define ANDEQ 259
|
||||
#define ARRAY 260
|
||||
#define ASM 261
|
||||
#define AUTO 262
|
||||
#define BREAK 263
|
||||
#define CASE 264
|
||||
#define CHAR 265
|
||||
#define CONST 266
|
||||
#define CONTINUE 267
|
||||
#define DECR 268
|
||||
#define DEFAULT 269
|
||||
#define DEREF 270
|
||||
#define DIVEQ 271
|
||||
#define DO 272
|
||||
#define DOUBLE 273
|
||||
#define ELLIPSIS 274
|
||||
#define ELSE 275
|
||||
#define ENUM 276
|
||||
#define EQL 277
|
||||
#define EXTERN 278
|
||||
#define FCON 279
|
||||
#define FLOAT 280
|
||||
#define FOR 281
|
||||
#define FUNCTION 282
|
||||
#define GEQ 283
|
||||
#define GOTO 284
|
||||
#define ICON 285
|
||||
#define ID 286
|
||||
#define IF 287
|
||||
#define INCR 288
|
||||
#define INT 289
|
||||
#define LEQ 290
|
||||
#define LONG 291
|
||||
#define LSHIFT 292
|
||||
#define LSHIFTEQ 293
|
||||
#define MODEQ 294
|
||||
#define MULEQ 295
|
||||
#define NEQ 296
|
||||
#define OREQ 297
|
||||
#define OROR 298
|
||||
#define POINTER 299
|
||||
#define REGISTER 300
|
||||
#define RETURN 301
|
||||
#define RSHIFT 302
|
||||
#define RSHIFTEQ 303
|
||||
#define SCON 304
|
||||
#define SHORT 305
|
||||
#define SIGNED 306
|
||||
#define SIZEOF 307
|
||||
#define STATIC 308
|
||||
#define STRUCT 309
|
||||
#define SUBEQ 310
|
||||
#define SWITCH 311
|
||||
#define TYPEDEF 312
|
||||
#define UNION 313
|
||||
#define UNSIGNED 314
|
||||
#define VOID 315
|
||||
#define VOLATILE 316
|
||||
#define WHILE 317
|
||||
#define XOREQ 318
|
||||
#define EOI 319
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#define BSIZE 8192
|
||||
|
||||
#define YYCTYPE uchar
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT s->lim
|
||||
#define YYMARKER s->ptr
|
||||
#define YYFILL(n) {cursor = fill(s, cursor);}
|
||||
|
||||
#define RET(i) {s->cur = cursor; return i;}
|
||||
|
||||
typedef struct Scanner {
|
||||
int fd;
|
||||
uchar *bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof;
|
||||
uint line;
|
||||
} Scanner;
|
||||
|
||||
uchar *fill(Scanner *s, uchar *cursor){
|
||||
if(!s->eof){
|
||||
uint cnt = s->tok - s->bot;
|
||||
if(cnt){
|
||||
memcpy(s->bot, s->tok, s->lim - s->tok);
|
||||
s->tok = s->bot;
|
||||
s->ptr -= cnt;
|
||||
cursor -= cnt;
|
||||
s->pos -= cnt;
|
||||
s->lim -= cnt;
|
||||
}
|
||||
if((s->top - s->lim) < BSIZE){
|
||||
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
|
||||
memcpy(buf, s->tok, s->lim - s->tok);
|
||||
s->tok = buf;
|
||||
s->ptr = &buf[s->ptr - s->bot];
|
||||
cursor = &buf[cursor - s->bot];
|
||||
s->pos = &buf[s->pos - s->bot];
|
||||
s->lim = &buf[s->lim - s->bot];
|
||||
s->top = &s->lim[BSIZE];
|
||||
free(s->bot);
|
||||
s->bot = buf;
|
||||
}
|
||||
if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
|
||||
s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
|
||||
}
|
||||
s->lim += cnt;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int scan(Scanner *s){
|
||||
uchar *cursor = s->cur;
|
||||
std:
|
||||
s->tok = cursor;
|
||||
/*!re2c
|
||||
any = [\000-\377];
|
||||
O = [0-7];
|
||||
D = [0-9];
|
||||
L = [a-zA-Z_];
|
||||
H = [a-fA-F0-9];
|
||||
E = [Ee] [+-]? D+;
|
||||
FS = [fFlL];
|
||||
IS = [uUlL]*;
|
||||
ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
|
||||
*/
|
||||
|
||||
/*!re2c
|
||||
"/*" { goto comment; }
|
||||
|
||||
L (L|D)* { RET(ID); }
|
||||
|
||||
("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
|
||||
(['] (ESC|any\[\n\\'])* ['])
|
||||
{ RET(ICON); }
|
||||
|
||||
(D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?)
|
||||
{ RET(FCON); }
|
||||
|
||||
(["] (ESC|any\[\n\\"])* ["])
|
||||
{ RET(SCON); }
|
||||
|
||||
"..." { RET(ELLIPSIS); }
|
||||
">>=" { RET(RSHIFTEQ); }
|
||||
"<<=" { RET(LSHIFTEQ); }
|
||||
"+=" { RET(ADDEQ); }
|
||||
"-=" { RET(SUBEQ); }
|
||||
"*=" { RET(MULEQ); }
|
||||
"/=" { RET(DIVEQ); }
|
||||
"%=" { RET(MODEQ); }
|
||||
"&=" { RET(ANDEQ); }
|
||||
"^=" { RET(XOREQ); }
|
||||
"|=" { RET(OREQ); }
|
||||
">>" { RET(RSHIFT); }
|
||||
"<<" { RET(LSHIFT); }
|
||||
"++" { RET(INCR); }
|
||||
"--" { RET(DECR); }
|
||||
"->" { RET(DEREF); }
|
||||
"&&" { RET(ANDAND); }
|
||||
"||" { RET(OROR); }
|
||||
"<=" { RET(LEQ); }
|
||||
">=" { RET(GEQ); }
|
||||
"==" { RET(EQL); }
|
||||
"!=" { RET(NEQ); }
|
||||
";" { RET(';'); }
|
||||
"{" { RET('{'); }
|
||||
"}" { RET('}'); }
|
||||
"," { RET(','); }
|
||||
":" { RET(':'); }
|
||||
"=" { RET('='); }
|
||||
"(" { RET('('); }
|
||||
")" { RET(')'); }
|
||||
"[" { RET('['); }
|
||||
"]" { RET(']'); }
|
||||
"." { RET('.'); }
|
||||
"&" { RET('&'); }
|
||||
"!" { RET('!'); }
|
||||
"~" { RET('~'); }
|
||||
"-" { RET('-'); }
|
||||
"+" { RET('+'); }
|
||||
"*" { RET('*'); }
|
||||
"/" { RET('/'); }
|
||||
"%" { RET('%'); }
|
||||
"<" { RET('<'); }
|
||||
">" { RET('>'); }
|
||||
"^" { RET('^'); }
|
||||
"|" { RET('|'); }
|
||||
"?" { RET('?'); }
|
||||
|
||||
|
||||
[ \t\v\f]+ { goto std; }
|
||||
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->pos = cursor; s->line++;
|
||||
goto std;
|
||||
}
|
||||
|
||||
any
|
||||
{
|
||||
printf("unexpected character: %c\n", *s->tok);
|
||||
goto std;
|
||||
}
|
||||
*/
|
||||
|
||||
comment:
|
||||
/*!re2c
|
||||
"*/" { goto std; }
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->tok = s->pos = cursor; s->line++;
|
||||
goto comment;
|
||||
}
|
||||
any { goto comment; }
|
||||
*/
|
||||
}
|
||||
|
||||
main(){
|
||||
Scanner in;
|
||||
int t;
|
||||
memset((char*) &in, 0, sizeof(in));
|
||||
in.fd = 0;
|
||||
while((t = scan(&in)) != EOI){
|
||||
/*
|
||||
printf("%d\t%.*s\n", t, in.cur - in.tok, in.tok);
|
||||
printf("%d\n", t);
|
||||
*/
|
||||
}
|
||||
close(in.fd);
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ADDEQ 257
|
||||
#define ANDAND 258
|
||||
#define ANDEQ 259
|
||||
#define ARRAY 260
|
||||
#define ASM 261
|
||||
#define AUTO 262
|
||||
#define BREAK 263
|
||||
#define CASE 264
|
||||
#define CHAR 265
|
||||
#define CONST 266
|
||||
#define CONTINUE 267
|
||||
#define DECR 268
|
||||
#define DEFAULT 269
|
||||
#define DEREF 270
|
||||
#define DIVEQ 271
|
||||
#define DO 272
|
||||
#define DOUBLE 273
|
||||
#define ELLIPSIS 274
|
||||
#define ELSE 275
|
||||
#define ENUM 276
|
||||
#define EQL 277
|
||||
#define EXTERN 278
|
||||
#define FCON 279
|
||||
#define FLOAT 280
|
||||
#define FOR 281
|
||||
#define FUNCTION 282
|
||||
#define GEQ 283
|
||||
#define GOTO 284
|
||||
#define ICON 285
|
||||
#define ID 286
|
||||
#define IF 287
|
||||
#define INCR 288
|
||||
#define INT 289
|
||||
#define LEQ 290
|
||||
#define LONG 291
|
||||
#define LSHIFT 292
|
||||
#define LSHIFTEQ 293
|
||||
#define MODEQ 294
|
||||
#define MULEQ 295
|
||||
#define NEQ 296
|
||||
#define OREQ 297
|
||||
#define OROR 298
|
||||
#define POINTER 299
|
||||
#define REGISTER 300
|
||||
#define RETURN 301
|
||||
#define RSHIFT 302
|
||||
#define RSHIFTEQ 303
|
||||
#define SCON 304
|
||||
#define SHORT 305
|
||||
#define SIGNED 306
|
||||
#define SIZEOF 307
|
||||
#define STATIC 308
|
||||
#define STRUCT 309
|
||||
#define SUBEQ 310
|
||||
#define SWITCH 311
|
||||
#define TYPEDEF 312
|
||||
#define UNION 313
|
||||
#define UNSIGNED 314
|
||||
#define VOID 315
|
||||
#define VOLATILE 316
|
||||
#define WHILE 317
|
||||
#define XOREQ 318
|
||||
#define EOI 319
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#define BSIZE 8192
|
||||
|
||||
#define YYCTYPE uchar
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT s->lim
|
||||
#define YYMARKER s->ptr
|
||||
#define YYFILL(n) {cursor = fill(s, cursor);}
|
||||
|
||||
#define RET(i) {s->cur = cursor; return i;}
|
||||
|
||||
typedef struct Scanner {
|
||||
int fd;
|
||||
uchar *bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof;
|
||||
uint line;
|
||||
} Scanner;
|
||||
|
||||
uchar *fill(Scanner *s, uchar *cursor){
|
||||
if(!s->eof){
|
||||
uint cnt = s->tok - s->bot;
|
||||
if(cnt){
|
||||
memcpy(s->bot, s->tok, s->lim - s->tok);
|
||||
s->tok = s->bot;
|
||||
s->ptr -= cnt;
|
||||
cursor -= cnt;
|
||||
s->pos -= cnt;
|
||||
s->lim -= cnt;
|
||||
}
|
||||
if((s->top - s->lim) < BSIZE){
|
||||
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
|
||||
memcpy(buf, s->tok, s->lim - s->tok);
|
||||
s->tok = buf;
|
||||
s->ptr = &buf[s->ptr - s->bot];
|
||||
cursor = &buf[cursor - s->bot];
|
||||
s->pos = &buf[s->pos - s->bot];
|
||||
s->lim = &buf[s->lim - s->bot];
|
||||
s->top = &s->lim[BSIZE];
|
||||
free(s->bot);
|
||||
s->bot = buf;
|
||||
}
|
||||
if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
|
||||
s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
|
||||
}
|
||||
s->lim += cnt;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int scan(Scanner *s){
|
||||
uchar *cursor = s->cur;
|
||||
std:
|
||||
s->tok = cursor;
|
||||
/*!re2c
|
||||
any = [\000-\377];
|
||||
O = [0-7];
|
||||
D = [0-9];
|
||||
L = [a-zA-Z_];
|
||||
I = L|D;
|
||||
H = [a-fA-F0-9];
|
||||
E = [Ee] [+-]? D+;
|
||||
FS = [fFlL];
|
||||
IS = [uUlL]*;
|
||||
ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
|
||||
X = any\[*/];
|
||||
*/
|
||||
|
||||
/*!re2c
|
||||
"/*" { goto comment; }
|
||||
|
||||
|
||||
L { RET(ID); }
|
||||
L I { RET(ID); }
|
||||
L I I { RET(ID); }
|
||||
L I I I { RET(ID); }
|
||||
L I I I I { RET(ID); }
|
||||
L I I I I I { RET(ID); }
|
||||
L I I I I I I { RET(ID); }
|
||||
L I I I I I I I { RET(ID); }
|
||||
L I* { RET(ID); }
|
||||
|
||||
("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
|
||||
(['] (ESC|any\[\n\\'])* ['])
|
||||
{ RET(ICON); }
|
||||
|
||||
(D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?)
|
||||
{ RET(FCON); }
|
||||
|
||||
(["] (ESC|any\[\n\\"])* ["])
|
||||
{ RET(SCON); }
|
||||
|
||||
"..." { RET(ELLIPSIS); }
|
||||
">>=" { RET(RSHIFTEQ); }
|
||||
"<<=" { RET(LSHIFTEQ); }
|
||||
"+=" { RET(ADDEQ); }
|
||||
"-=" { RET(SUBEQ); }
|
||||
"*=" { RET(MULEQ); }
|
||||
"/=" { RET(DIVEQ); }
|
||||
"%=" { RET(MODEQ); }
|
||||
"&=" { RET(ANDEQ); }
|
||||
"^=" { RET(XOREQ); }
|
||||
"|=" { RET(OREQ); }
|
||||
">>" { RET(RSHIFT); }
|
||||
"<<" { RET(LSHIFT); }
|
||||
"++" { RET(INCR); }
|
||||
"--" { RET(DECR); }
|
||||
"->" { RET(DEREF); }
|
||||
"&&" { RET(ANDAND); }
|
||||
"||" { RET(OROR); }
|
||||
"<=" { RET(LEQ); }
|
||||
">=" { RET(GEQ); }
|
||||
"==" { RET(EQL); }
|
||||
"!=" { RET(NEQ); }
|
||||
";" { RET(';'); }
|
||||
"{" { RET('{'); }
|
||||
"}" { RET('}'); }
|
||||
"," { RET(','); }
|
||||
":" { RET(':'); }
|
||||
"=" { RET('='); }
|
||||
"(" { RET('('); }
|
||||
")" { RET(')'); }
|
||||
"[" { RET('['); }
|
||||
"]" { RET(']'); }
|
||||
"." { RET('.'); }
|
||||
"&" { RET('&'); }
|
||||
"!" { RET('!'); }
|
||||
"~" { RET('~'); }
|
||||
"-" { RET('-'); }
|
||||
"+" { RET('+'); }
|
||||
"*" { RET('*'); }
|
||||
"/" { RET('/'); }
|
||||
"%" { RET('%'); }
|
||||
"<" { RET('<'); }
|
||||
">" { RET('>'); }
|
||||
"^" { RET('^'); }
|
||||
"|" { RET('|'); }
|
||||
"?" { RET('?'); }
|
||||
|
||||
|
||||
[ \t\v\f]+ { goto std; }
|
||||
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->pos = cursor; s->line++;
|
||||
goto std;
|
||||
}
|
||||
|
||||
any
|
||||
{
|
||||
printf("unexpected character: %c\n", *s->tok);
|
||||
goto std;
|
||||
}
|
||||
*/
|
||||
|
||||
comment:
|
||||
/*!re2c
|
||||
"*/" { goto std; }
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->tok = s->pos = cursor; s->line++;
|
||||
goto comment;
|
||||
}
|
||||
X { goto comment; }
|
||||
X X { goto comment; }
|
||||
X X X { goto comment; }
|
||||
X X X X { goto comment; }
|
||||
X X X X X { goto comment; }
|
||||
X X X X X X { goto comment; }
|
||||
X X X X X X X { goto comment; }
|
||||
X X X X X X X X { goto comment; }
|
||||
any { goto comment; }
|
||||
*/
|
||||
}
|
||||
|
||||
main(){
|
||||
Scanner in;
|
||||
int t;
|
||||
memset((char*) &in, 0, sizeof(in));
|
||||
in.fd = 0;
|
||||
while((t = scan(&in)) != EOI){
|
||||
/*
|
||||
printf("%d\t%.*s\n", t, in.cur - in.tok, in.tok);
|
||||
printf("%d\n", t);
|
||||
*/
|
||||
}
|
||||
close(in.fd);
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#define BSIZE 8192
|
||||
|
||||
#define YYCTYPE uchar
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT s->lim
|
||||
#define YYMARKER s->ptr
|
||||
#define YYFILL {cursor = fill(s, cursor);}
|
||||
|
||||
#define RETURN(i) {s->cur = cursor; return i;}
|
||||
|
||||
typedef struct Scanner {
|
||||
int fd;
|
||||
uchar *bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof;
|
||||
uint line;
|
||||
} Scanner;
|
||||
|
||||
uchar *fill(Scanner *s, uchar *cursor){
|
||||
if(!s->eof){
|
||||
uint cnt = s->tok - s->bot;
|
||||
if(cnt){
|
||||
memcpy(s->bot, s->tok, s->lim - s->tok);
|
||||
s->tok = s->bot;
|
||||
s->ptr -= cnt;
|
||||
cursor -= cnt;
|
||||
s->pos -= cnt;
|
||||
s->lim -= cnt;
|
||||
}
|
||||
if((s->top - s->lim) < BSIZE){
|
||||
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
|
||||
memcpy(buf, s->tok, s->lim - s->tok);
|
||||
s->tok = buf;
|
||||
s->ptr = &buf[s->ptr - s->bot];
|
||||
cursor = &buf[cursor - s->bot];
|
||||
s->pos = &buf[s->pos - s->bot];
|
||||
s->lim = &buf[s->lim - s->bot];
|
||||
s->top = &s->lim[BSIZE];
|
||||
free(s->bot);
|
||||
s->bot = buf;
|
||||
}
|
||||
if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
|
||||
s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
|
||||
}
|
||||
s->lim += cnt;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int scan(Scanner *s){
|
||||
uchar *cursor = s->cur;
|
||||
uint depth;
|
||||
std:
|
||||
s->tok = cursor;
|
||||
/*!re2c
|
||||
any = [\000-\377];
|
||||
digit = [0-9];
|
||||
letter = [a-zA-Z];
|
||||
*/
|
||||
|
||||
/*!re2c
|
||||
"(*" { depth = 1; goto comment; }
|
||||
|
||||
digit + {RETURN(1);}
|
||||
digit + / ".." {RETURN(1);}
|
||||
[0-7] + "B" {RETURN(2);}
|
||||
[0-7] + "C" {RETURN(3);}
|
||||
digit [0-9A-F] * "H" {RETURN(4);}
|
||||
digit + "." digit * ("E" ([+-]) ? digit +) ? {RETURN(5);}
|
||||
['] (any\[\n']) * ['] | ["] (any\[\n"]) * ["] {RETURN(6);}
|
||||
|
||||
"#" {RETURN(7);}
|
||||
"&" {RETURN(8);}
|
||||
"(" {RETURN(9);}
|
||||
")" {RETURN(10);}
|
||||
"*" {RETURN(11);}
|
||||
"+" {RETURN(12);}
|
||||
"," {RETURN(13);}
|
||||
"-" {RETURN(14);}
|
||||
"." {RETURN(15);}
|
||||
".." {RETURN(16);}
|
||||
"/" {RETURN(17);}
|
||||
":" {RETURN(18);}
|
||||
":=" {RETURN(19);}
|
||||
";" {RETURN(20);}
|
||||
"<" {RETURN(21);}
|
||||
"<=" {RETURN(22);}
|
||||
"<>" {RETURN(23);}
|
||||
"=" {RETURN(24);}
|
||||
">" {RETURN(25);}
|
||||
">=" {RETURN(26);}
|
||||
"[" {RETURN(27);}
|
||||
"]" {RETURN(28);}
|
||||
"^" {RETURN(29);}
|
||||
"{" {RETURN(30);}
|
||||
"|" {RETURN(31);}
|
||||
"}" {RETURN(32);}
|
||||
"~" {RETURN(33);}
|
||||
|
||||
"AND" {RETURN(34);}
|
||||
"ARRAY" {RETURN(35);}
|
||||
"BEGIN" {RETURN(36);}
|
||||
"BY" {RETURN(37);}
|
||||
"CASE" {RETURN(38);}
|
||||
"CONST" {RETURN(39);}
|
||||
"DEFINITION" {RETURN(40);}
|
||||
"DIV" {RETURN(41);}
|
||||
"DO" {RETURN(42);}
|
||||
"ELSE" {RETURN(43);}
|
||||
"ELSIF" {RETURN(44);}
|
||||
"END" {RETURN(45);}
|
||||
"EXIT" {RETURN(46);}
|
||||
"EXPORT" {RETURN(47);}
|
||||
"FOR" {RETURN(48);}
|
||||
"FROM" {RETURN(49);}
|
||||
"IF" {RETURN(50);}
|
||||
"IMPLEMENTATION" {RETURN(51);}
|
||||
"IMPORT" {RETURN(52);}
|
||||
"IN" {RETURN(53);}
|
||||
"LOOP" {RETURN(54);}
|
||||
"MOD" {RETURN(55);}
|
||||
"MODULE" {RETURN(56);}
|
||||
"NOT" {RETURN(57);}
|
||||
"OF" {RETURN(58);}
|
||||
"OR" {RETURN(59);}
|
||||
"POINTER" {RETURN(60);}
|
||||
"PROCEDURE" {RETURN(61);}
|
||||
"QUALIFIED" {RETURN(62);}
|
||||
"RECORD" {RETURN(63);}
|
||||
"REPEAT" {RETURN(64);}
|
||||
"RETURN" {RETURN(65);}
|
||||
"SET" {RETURN(66);}
|
||||
"THEN" {RETURN(67);}
|
||||
"TO" {RETURN(68);}
|
||||
"TYPE" {RETURN(69);}
|
||||
"UNTIL" {RETURN(70);}
|
||||
"VAR" {RETURN(71);}
|
||||
"WHILE" {RETURN(72);}
|
||||
"WITH" {RETURN(73);}
|
||||
|
||||
letter (letter | digit) * {RETURN(74);}
|
||||
|
||||
[ \t]+ { goto std; }
|
||||
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RETURN(0);
|
||||
s->pos = cursor; s->line++;
|
||||
goto std;
|
||||
}
|
||||
|
||||
any
|
||||
{
|
||||
printf("unexpected character: %c\n", *s->tok);
|
||||
goto std;
|
||||
}
|
||||
*/
|
||||
comment:
|
||||
/*!re2c
|
||||
"*)"
|
||||
{
|
||||
if(--depth == 0)
|
||||
goto std;
|
||||
else
|
||||
goto comment;
|
||||
}
|
||||
"(*" { ++depth; goto comment; }
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RETURN(0);
|
||||
s->tok = s->pos = cursor; s->line++;
|
||||
goto comment;
|
||||
}
|
||||
any { goto comment; }
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
void putStr(FILE *o, char *s, uint l){
|
||||
while(l-- > 0)
|
||||
putc(*s++, o);
|
||||
}
|
||||
*/
|
||||
|
||||
main(){
|
||||
Scanner in;
|
||||
memset((char*) &in, 0, sizeof(in));
|
||||
in.fd = 0;
|
||||
while(scan(&in)){
|
||||
/*
|
||||
putc('<', stdout);
|
||||
putStr(stdout, (char*) in.tok, in.cur - in.tok);
|
||||
putc('>', stdout);
|
||||
putc('\n', stdout);
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ADDEQ 257
|
||||
#define ANDAND 258
|
||||
#define ANDEQ 259
|
||||
#define ARRAY 260
|
||||
#define ASM 261
|
||||
#define AUTO 262
|
||||
#define BREAK 263
|
||||
#define CASE 264
|
||||
#define CHAR 265
|
||||
#define CONST 266
|
||||
#define CONTINUE 267
|
||||
#define DECR 268
|
||||
#define DEFAULT 269
|
||||
#define DEREF 270
|
||||
#define DIVEQ 271
|
||||
#define DO 272
|
||||
#define DOUBLE 273
|
||||
#define ELLIPSIS 274
|
||||
#define ELSE 275
|
||||
#define ENUM 276
|
||||
#define EQL 277
|
||||
#define EXTERN 278
|
||||
#define FCON 279
|
||||
#define FLOAT 280
|
||||
#define FOR 281
|
||||
#define FUNCTION 282
|
||||
#define GEQ 283
|
||||
#define GOTO 284
|
||||
#define ICON 285
|
||||
#define ID 286
|
||||
#define IF 287
|
||||
#define INCR 288
|
||||
#define INT 289
|
||||
#define LEQ 290
|
||||
#define LONG 291
|
||||
#define LSHIFT 292
|
||||
#define LSHIFTEQ 293
|
||||
#define MODEQ 294
|
||||
#define MULEQ 295
|
||||
#define NEQ 296
|
||||
#define OREQ 297
|
||||
#define OROR 298
|
||||
#define POINTER 299
|
||||
#define REGISTER 300
|
||||
#define RETURN 301
|
||||
#define RSHIFT 302
|
||||
#define RSHIFTEQ 303
|
||||
#define SCON 304
|
||||
#define SHORT 305
|
||||
#define SIGNED 306
|
||||
#define SIZEOF 307
|
||||
#define STATIC 308
|
||||
#define STRUCT 309
|
||||
#define SUBEQ 310
|
||||
#define SWITCH 311
|
||||
#define TYPEDEF 312
|
||||
#define UNION 313
|
||||
#define UNSIGNED 314
|
||||
#define VOID 315
|
||||
#define VOLATILE 316
|
||||
#define WHILE 317
|
||||
#define XOREQ 318
|
||||
#define EOI 319
|
||||
#define PP_INCLUDE 500
|
||||
#define PP_LINE 501
|
||||
#define PP_DEFINE 502
|
||||
#define PP_UNDEF 503
|
||||
#define PP_IF 504
|
||||
#define PP_IFDEF 505
|
||||
#define PP_IFNDEF 506
|
||||
#define PP_ELSE 507
|
||||
#define PP_ELIF 508
|
||||
#define PP_ENDIF 509
|
||||
#define PP_ERROR 510
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#define BSIZE 12
|
||||
//8192
|
||||
|
||||
#define YYCTYPE uchar
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT s->lim
|
||||
#define YYMARKER s->ptr
|
||||
#define YYFILL(n) {cursor = fill(s, cursor);}
|
||||
|
||||
#define RET(i) {s->cur = cursor; return i;}
|
||||
|
||||
typedef struct Scanner {
|
||||
int fd;
|
||||
uchar *bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof;
|
||||
uint line;
|
||||
} Scanner;
|
||||
|
||||
uchar *fill(Scanner *s, uchar *cursor){
|
||||
if(!s->eof) {
|
||||
uint cnt = s->tok - s->bot;
|
||||
if(cnt){
|
||||
memcpy(s->bot, s->tok, s->lim - s->tok);
|
||||
s->tok = s->bot;
|
||||
s->ptr -= cnt;
|
||||
cursor -= cnt;
|
||||
s->pos -= cnt;
|
||||
s->lim -= cnt;
|
||||
}
|
||||
if((s->top - s->lim) < BSIZE){
|
||||
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
|
||||
memcpy(buf, s->tok, s->lim - s->tok);
|
||||
s->tok = buf;
|
||||
s->ptr = &buf[s->ptr - s->bot];
|
||||
cursor = &buf[cursor - s->bot];
|
||||
s->pos = &buf[s->pos - s->bot];
|
||||
s->lim = &buf[s->lim - s->bot];
|
||||
s->top = &s->lim[BSIZE];
|
||||
free(s->bot);
|
||||
s->bot = buf;
|
||||
}
|
||||
if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
|
||||
s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
|
||||
}
|
||||
s->lim += cnt;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int scan(Scanner *s){
|
||||
uchar *cursor = s->cur;
|
||||
std:
|
||||
s->tok = cursor;
|
||||
/*!re2c
|
||||
any = [\000-\377];
|
||||
O = [0-7];
|
||||
D = [0-9];
|
||||
L = [a-zA-Z_];
|
||||
H = [a-fA-F0-9];
|
||||
E = [Ee] [+-]? D+;
|
||||
FS = [fFlL];
|
||||
IS = [uUlL]*;
|
||||
ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
|
||||
PP = "#" [ \t]*;
|
||||
*/
|
||||
|
||||
/*!re2c
|
||||
"/*" { goto comment; }
|
||||
|
||||
"auto" { RET(AUTO); }
|
||||
"break" { RET(BREAK); }
|
||||
"case" { RET(CASE); }
|
||||
"char" { RET(CHAR); }
|
||||
"const" { RET(CONST); }
|
||||
"continue" { RET(CONTINUE); }
|
||||
"default" { RET(DEFAULT); }
|
||||
"do" { RET(DO); }
|
||||
"double" { RET(DOUBLE); }
|
||||
"else" { RET(ELSE); }
|
||||
"enum" { RET(ENUM); }
|
||||
"extern" { RET(EXTERN); }
|
||||
"float" { RET(FLOAT); }
|
||||
"for" { RET(FOR); }
|
||||
"goto" { RET(GOTO); }
|
||||
"if" { RET(IF); }
|
||||
"int" { RET(INT); }
|
||||
"long" { RET(LONG); }
|
||||
"register" { RET(REGISTER); }
|
||||
"return" { RET(RETURN); }
|
||||
"short" { RET(SHORT); }
|
||||
"signed" { RET(SIGNED); }
|
||||
"sizeof" { RET(SIZEOF); }
|
||||
"static" { RET(STATIC); }
|
||||
"struct" { RET(STRUCT); }
|
||||
"switch" { RET(SWITCH); }
|
||||
"typedef" { RET(TYPEDEF); }
|
||||
"union" { RET(UNION); }
|
||||
"unsigned" { RET(UNSIGNED); }
|
||||
"void" { RET(VOID); }
|
||||
"volatile" { RET(VOLATILE); }
|
||||
"while" { RET(WHILE); }
|
||||
|
||||
L (L|D)* { RET(ID); }
|
||||
|
||||
("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
|
||||
(['] (ESC|any\[\n\\'])* ['])
|
||||
{ RET(ICON); }
|
||||
|
||||
(D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?)
|
||||
{ RET(FCON); }
|
||||
|
||||
(["] (ESC|any\[\n\\"])* ["])
|
||||
{ RET(SCON); }
|
||||
|
||||
"..." { RET(ELLIPSIS); }
|
||||
">>=" { RET(RSHIFTEQ); }
|
||||
"<<=" { RET(LSHIFTEQ); }
|
||||
"+=" { RET(ADDEQ); }
|
||||
"-=" { RET(SUBEQ); }
|
||||
"*=" { RET(MULEQ); }
|
||||
"/=" { RET(DIVEQ); }
|
||||
"%=" { RET(MODEQ); }
|
||||
"&=" { RET(ANDEQ); }
|
||||
"^=" { RET(XOREQ); }
|
||||
"|=" { RET(OREQ); }
|
||||
">>" { RET(RSHIFT); }
|
||||
"<<" { RET(LSHIFT); }
|
||||
"++" { RET(INCR); }
|
||||
"--" { RET(DECR); }
|
||||
"->" { RET(DEREF); }
|
||||
"&&" { RET(ANDAND); }
|
||||
"||" { RET(OROR); }
|
||||
"<=" { RET(LEQ); }
|
||||
">=" { RET(GEQ); }
|
||||
"==" { RET(EQL); }
|
||||
"!=" { RET(NEQ); }
|
||||
";" { RET(';'); }
|
||||
"{" { RET('{'); }
|
||||
"}" { RET('}'); }
|
||||
"," { RET(','); }
|
||||
":" { RET(':'); }
|
||||
"=" { RET('='); }
|
||||
"(" { RET('('); }
|
||||
")" { RET(')'); }
|
||||
"[" { RET('['); }
|
||||
"]" { RET(']'); }
|
||||
"." { RET('.'); }
|
||||
"&" { RET('&'); }
|
||||
"!" { RET('!'); }
|
||||
"~" { RET('~'); }
|
||||
"-" { RET('-'); }
|
||||
"+" { RET('+'); }
|
||||
"*" { RET('*'); }
|
||||
"/" { RET('/'); }
|
||||
"%" { RET('%'); }
|
||||
"<" { RET('<'); }
|
||||
">" { RET('>'); }
|
||||
"^" { RET('^'); }
|
||||
"|" { RET('|'); }
|
||||
"?" { RET('?'); }
|
||||
|
||||
PP "include" { RET(PP_INCLUDE); }
|
||||
PP "line" { RET(PP_LINE); }
|
||||
PP "define" { RET(PP_DEFINE); }
|
||||
PP "undef" { RET(PP_UNDEF); }
|
||||
PP "if" { RET(PP_IF); }
|
||||
PP "ifdef" { RET(PP_IFDEF); }
|
||||
PP "ifndef" { RET(PP_IFNDEF); }
|
||||
PP "else" { RET(PP_ELSE); }
|
||||
PP "elif" { RET(PP_ELIF); }
|
||||
PP "endif" { RET(PP_ENDIF); }
|
||||
PP "error" { RET(PP_ERROR); }
|
||||
|
||||
[ \t\v\f]+ { goto std; }
|
||||
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->pos = cursor; s->line++;
|
||||
goto std;
|
||||
}
|
||||
|
||||
any
|
||||
{
|
||||
printf("unexpected character: %c\n", *s->tok);
|
||||
goto std;
|
||||
}
|
||||
*/
|
||||
|
||||
comment:
|
||||
/*!re2c
|
||||
"*/" { goto std; }
|
||||
"\n"
|
||||
{
|
||||
if(cursor == s->eof) RET(EOI);
|
||||
s->tok = s->pos = cursor; s->line++;
|
||||
goto comment;
|
||||
}
|
||||
any { goto comment; }
|
||||
*/
|
||||
}
|
||||
|
||||
main(){
|
||||
Scanner in;
|
||||
int t;
|
||||
memset((char*) &in, 0, sizeof(in));
|
||||
in.fd = 0;
|
||||
while((t = scan(&in)) != EOI){
|
||||
|
||||
printf("%d\t%.*s\n", t, in.cur - in.tok, in.tok);
|
||||
|
||||
}
|
||||
close(in.fd);
|
||||
}
|
||||
@@ -1,340 +0,0 @@
|
||||
/*
|
||||
* A push-model scanner example for re2c -f
|
||||
* Written Mon Apr 11 2005 by mgix@mgix.com
|
||||
* This file is in the public domain.
|
||||
*
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
#define TOKENS \
|
||||
\
|
||||
TOK(kEOF) \
|
||||
TOK(kEOL) \
|
||||
TOK(kUnknown) \
|
||||
TOK(kIdentifier) \
|
||||
TOK(kDecimalConstant) \
|
||||
\
|
||||
TOK(kEqual) \
|
||||
TOK(kLeftParen) \
|
||||
TOK(kRightParen) \
|
||||
TOK(kMinus) \
|
||||
TOK(kPlus) \
|
||||
TOK(kStar) \
|
||||
TOK(kSlash) \
|
||||
\
|
||||
TOK(kIf) \
|
||||
TOK(kFor) \
|
||||
TOK(kElse) \
|
||||
TOK(kGoto) \
|
||||
TOK(kBreak) \
|
||||
TOK(kWhile) \
|
||||
TOK(kReturn) \
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
static const char *tokenNames[] =
|
||||
{
|
||||
#define TOK(x) #x,
|
||||
TOKENS
|
||||
#undef TOK
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
class PushScanner
|
||||
{
|
||||
public:
|
||||
|
||||
enum Token
|
||||
{
|
||||
#define TOK(x) x,
|
||||
TOKENS
|
||||
#undef TOK
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
bool eof;
|
||||
int32_t state;
|
||||
|
||||
uint8_t *limit;
|
||||
uint8_t *start;
|
||||
uint8_t *cursor;
|
||||
uint8_t *marker;
|
||||
|
||||
uint8_t *buffer;
|
||||
uint8_t *bufferEnd;
|
||||
|
||||
uint8_t yych;
|
||||
uint32_t yyaccept;
|
||||
|
||||
public:
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
PushScanner()
|
||||
{
|
||||
limit = 0;
|
||||
start = 0;
|
||||
state = -1;
|
||||
cursor = 0;
|
||||
marker = 0;
|
||||
buffer = 0;
|
||||
eof = false;
|
||||
bufferEnd = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
~PushScanner()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void send(
|
||||
Token token
|
||||
)
|
||||
{
|
||||
size_t tokenSize = cursor-start;
|
||||
const char *tokenName = tokenNames[token];
|
||||
printf(
|
||||
"scanner is pushing out a token of type %d (%s)",
|
||||
token,
|
||||
tokenName
|
||||
);
|
||||
|
||||
if(token==kEOF) putchar('\n');
|
||||
else
|
||||
{
|
||||
size_t tokenNameSize = strlen(tokenNames[token]);
|
||||
size_t padSize = 20-(20<tokenNameSize ? 20 : tokenNameSize);
|
||||
for(size_t i=0; i<padSize; ++i) putchar(' ');
|
||||
printf(" : ---->");
|
||||
|
||||
fwrite(
|
||||
start,
|
||||
tokenSize,
|
||||
1,
|
||||
stdout
|
||||
);
|
||||
|
||||
printf("<----\n");
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
uint32_t push(
|
||||
const void *input,
|
||||
ssize_t inputSize
|
||||
)
|
||||
{
|
||||
printf(
|
||||
"scanner is receiving a new data batch of length %d\n"
|
||||
"scanner continues with saved state = %d\n",
|
||||
inputSize,
|
||||
state
|
||||
);
|
||||
|
||||
/*
|
||||
* Data source is signaling end of file when batch size
|
||||
* is less than maxFill. This is slightly annoying because
|
||||
* maxFill is a value that can only be known after re2c does
|
||||
* its thing. Practically though, maxFill is never bigger than
|
||||
* the longest keyword, so given our grammar, 32 is a safe bet.
|
||||
*/
|
||||
uint8_t null[64];
|
||||
const ssize_t maxFill = 32;
|
||||
if(inputSize<maxFill)
|
||||
{
|
||||
eof = true;
|
||||
input = null;
|
||||
inputSize = sizeof(null);
|
||||
memset(null, 0, sizeof(null));
|
||||
}
|
||||
|
||||
/*
|
||||
* When we get here, we have a partially
|
||||
* consumed buffer which is in the following state:
|
||||
* last valid char last valid buffer spot
|
||||
* v v
|
||||
* +-------------------+-------------+---------------+-------------+----------------------+
|
||||
* ^ ^ ^ ^ ^ ^
|
||||
* buffer start marker cursor limit bufferEnd
|
||||
*
|
||||
* We need to stretch the buffer and concatenate the new chunk of input to it
|
||||
*
|
||||
*/
|
||||
size_t used = limit-buffer;
|
||||
size_t needed = used+inputSize;
|
||||
size_t allocated = bufferEnd-buffer;
|
||||
if(allocated<needed)
|
||||
{
|
||||
size_t limitOffset = limit-buffer;
|
||||
size_t startOffset = start-buffer;
|
||||
size_t markerOffset = marker-buffer;
|
||||
size_t cursorOffset = cursor-buffer;
|
||||
|
||||
buffer = (uint8_t*)realloc(buffer, needed);
|
||||
bufferEnd = needed+buffer;
|
||||
|
||||
marker = markerOffset + buffer;
|
||||
cursor = cursorOffset + buffer;
|
||||
start = buffer + startOffset;
|
||||
limit = limitOffset + buffer;
|
||||
}
|
||||
memcpy(limit, input, inputSize);
|
||||
limit += inputSize;
|
||||
|
||||
// The scanner starts here
|
||||
#define YYLIMIT limit
|
||||
#define YYCURSOR cursor
|
||||
#define YYMARKER marker
|
||||
#define YYCTYPE uint8_t
|
||||
|
||||
#define SKIP(x) { start = cursor; goto yy0; }
|
||||
#define SEND(x) { send(x); SKIP(); }
|
||||
#define YYFILL(n) { goto fill; }
|
||||
|
||||
#define YYGETSTATE() state
|
||||
#define YYSETSTATE(x) { state = (x); }
|
||||
|
||||
start:
|
||||
|
||||
/*!re2c
|
||||
|
||||
eol = "\n";
|
||||
eof = "\000";
|
||||
digit = [0-9];
|
||||
integer = digit+;
|
||||
alpha = [A-Za-z_];
|
||||
any = [\000-\0377];
|
||||
space = [ \h\t\v\f\r];
|
||||
|
||||
"if" { SEND(kIf); }
|
||||
"for" { SEND(kFor); }
|
||||
"else" { SEND(kElse); }
|
||||
"goto" { SEND(kGoto); }
|
||||
"break" { SEND(kBreak); }
|
||||
"while" { SEND(kWhile); }
|
||||
"return" { SEND(kReturn); }
|
||||
alpha (alpha|digit)* { SEND(kIdentifier); }
|
||||
integer { SEND(kDecimalConstant);}
|
||||
|
||||
"=" { SEND(kEqual); }
|
||||
"(" { SEND(kLeftParen); }
|
||||
")" { SEND(kRightParen); }
|
||||
"-" { SEND(kMinus); }
|
||||
"+" { SEND(kPlus); }
|
||||
"*" { SEND(kStar); }
|
||||
"/" { SEND(kSlash); }
|
||||
|
||||
eol { SKIP(); }
|
||||
space { SKIP(); }
|
||||
eof { send(kEOF); return 1; }
|
||||
any { SEND(kUnknown); }
|
||||
*/
|
||||
|
||||
fill:
|
||||
ssize_t unfinishedSize = cursor-start;
|
||||
printf(
|
||||
"scanner needs a refill. Exiting for now with:\n"
|
||||
" saved fill state = %d\n"
|
||||
" unfinished token size = %d\n",
|
||||
state,
|
||||
unfinishedSize
|
||||
);
|
||||
|
||||
if(0<unfinishedSize && start<limit)
|
||||
{
|
||||
printf(" unfinished token is :");
|
||||
fwrite(start, 1, cursor-start, stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
/*
|
||||
* Once we get here, we can get rid of
|
||||
* everything before start and after limit.
|
||||
*/
|
||||
if(eof==true) goto start;
|
||||
if(buffer<start)
|
||||
{
|
||||
size_t startOffset = start-buffer;
|
||||
memmove(buffer, start, limit-start);
|
||||
marker -= startOffset;
|
||||
cursor -= startOffset;
|
||||
limit -= startOffset;
|
||||
start -= startOffset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
// Parse cmd line
|
||||
int input = 0;
|
||||
if(1<argc)
|
||||
{
|
||||
input = open(argv[1], O_RDONLY | O_BINARY);
|
||||
if(input<0)
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"could not open file %s\n",
|
||||
argv[1]
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenize input file by pushing batches
|
||||
* of data one by one into the scanner.
|
||||
*/
|
||||
const size_t batchSize = 256;
|
||||
uint8_t buffer[batchSize];
|
||||
PushScanner scanner;
|
||||
while(1)
|
||||
{
|
||||
ssize_t n = read(input, buffer, batchSize);
|
||||
scanner.push(buffer, n);
|
||||
if(n<batchSize) break;
|
||||
}
|
||||
scanner.push(0, -1);
|
||||
close(input);
|
||||
|
||||
// Done
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define RET(n) printf("%d\n", n); return n
|
||||
|
||||
int scan(char *s, int l){
|
||||
char *p = s;
|
||||
char *q;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n)
|
||||
/*!re2c
|
||||
'a'{1}"\n" {RET(1);}
|
||||
'a'{2,3}"\n" {RET(2);}
|
||||
'a'{6}"\n" {RET(4);}
|
||||
'a'{4,}"\n" {RET(3);}
|
||||
[^aq]|"\n" {RET(0);}
|
||||
*/
|
||||
}
|
||||
|
||||
#define do_scan(str) scan(str, strlen(str))
|
||||
|
||||
main()
|
||||
{
|
||||
do_scan("a\n");
|
||||
do_scan("aa\n");
|
||||
do_scan("aaa\n");
|
||||
do_scan("aaaa\n");
|
||||
do_scan("q");
|
||||
do_scan("a");
|
||||
do_scan("A\n");
|
||||
do_scan("AA\n");
|
||||
do_scan("aAa\n");
|
||||
do_scan("AaaA\n");
|
||||
do_scan("Q");
|
||||
do_scan("AaaAa\n");
|
||||
do_scan("AaaAaA\n");
|
||||
do_scan("A");
|
||||
do_scan("\n");
|
||||
do_scan("0");
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Replacement modules for an existing REXX interpreter. Not standalone.
|
||||
@@ -1,319 +0,0 @@
|
||||
#include "scanio.h"
|
||||
#include "scanner.h"
|
||||
|
||||
#define CURSOR ch
|
||||
#define LOADCURSOR ch = *cursor;
|
||||
#define ADVANCE cursor++;
|
||||
#define BACK(n) cursor -= (n);
|
||||
#define CHECK(n) if((ScanCB.lim - cursor) < (n)){cursor = ScanFill(cursor);}
|
||||
#define MARK(n) ScanCB.ptr = cursor; sel = (n);
|
||||
#define REVERT cursor = ScanCB.ptr;
|
||||
#define MARKER sel
|
||||
|
||||
#define RETURN(i) {ScanCB.cur = cursor; return i;}
|
||||
|
||||
int ScanToken(){
|
||||
uchar *cursor = ScanCB.cur;
|
||||
unsigned sel;
|
||||
uchar ch;
|
||||
ScanCB.tok = cursor;
|
||||
ScanCB.eot = NULL;
|
||||
/*!re2c
|
||||
all = [\000-\377];
|
||||
eof = [\000];
|
||||
any = all\eof;
|
||||
letter = [a-z]|[A-Z];
|
||||
digit = [0-9];
|
||||
symchr = letter|digit|[.!?_];
|
||||
const = (digit|[.])symchr*([eE][+-]?digit+)?;
|
||||
simple = (symchr\(digit|[.]))(symchr\[.])*;
|
||||
stem = simple [.];
|
||||
symbol = symchr*;
|
||||
sqstr = ['] ((any\['\n])|(['][']))* ['];
|
||||
dqstr = ["] ((any\["\n])|(["]["]))* ["];
|
||||
str = sqstr|dqstr;
|
||||
ob = [ \t]*;
|
||||
not = [\\~];
|
||||
A = [aA];
|
||||
B = [bB];
|
||||
C = [cC];
|
||||
D = [dD];
|
||||
E = [eE];
|
||||
F = [fF];
|
||||
G = [gG];
|
||||
H = [hH];
|
||||
I = [iI];
|
||||
J = [jJ];
|
||||
K = [kK];
|
||||
L = [lL];
|
||||
M = [mM];
|
||||
N = [nN];
|
||||
O = [oO];
|
||||
P = [pP];
|
||||
Q = [qQ];
|
||||
R = [rR];
|
||||
S = [sS];
|
||||
T = [tT];
|
||||
U = [uU];
|
||||
V = [vV];
|
||||
W = [wW];
|
||||
X = [xX];
|
||||
Y = [yY];
|
||||
Z = [zZ];
|
||||
*/
|
||||
|
||||
scan:
|
||||
/*!re2c
|
||||
"\n"
|
||||
{
|
||||
++(ScanCB.lineNum);
|
||||
ScanCB.linePos = ScanCB.pos + (cursor - ScanCB.mrk);
|
||||
RETURN(SU_EOL);
|
||||
}
|
||||
"|" ob "|"
|
||||
{ RETURN(OP_CONCAT); }
|
||||
"+"
|
||||
{ RETURN(OP_PLUS); }
|
||||
"-"
|
||||
{ RETURN(OP_MINUS); }
|
||||
"*"
|
||||
{ RETURN(OP_MULT); }
|
||||
"/"
|
||||
{ RETURN(OP_DIV); }
|
||||
"%"
|
||||
{ RETURN(OP_IDIV); }
|
||||
"/" ob "/"
|
||||
{ RETURN(OP_REMAIN); }
|
||||
"*" ob "*"
|
||||
{ RETURN(OP_POWER); }
|
||||
"="
|
||||
{ RETURN(OP_EQUAL); }
|
||||
not ob "=" | "<" ob ">" | ">" ob "<"
|
||||
{ RETURN(OP_EQUAL_N); }
|
||||
">"
|
||||
{ RETURN(OP_GT); }
|
||||
"<"
|
||||
{ RETURN(OP_LT); }
|
||||
">" ob "=" | not ob "<"
|
||||
{ RETURN(OP_GE); }
|
||||
"<" ob "=" | not ob ">"
|
||||
{ RETURN(OP_LE); }
|
||||
"=" ob "="
|
||||
{ RETURN(OP_EQUAL_EQ); }
|
||||
not ob "=" ob "="
|
||||
{ RETURN(OP_EQUAL_EQ_N); }
|
||||
">" ob ">"
|
||||
{ RETURN(OP_GT_STRICT); }
|
||||
"<" ob "<"
|
||||
{ RETURN(OP_LT_STRICT); }
|
||||
">" ob ">" ob "=" | not ob "<" ob "<"
|
||||
{ RETURN(OP_GE_STRICT); }
|
||||
"<" ob "<" ob "=" | not ob ">" ob ">"
|
||||
{ RETURN(OP_LE_STRICT); }
|
||||
"&"
|
||||
{ RETURN(OP_AND); }
|
||||
"|"
|
||||
{ RETURN(OP_OR); }
|
||||
"&" ob "&"
|
||||
{ RETURN(OP_XOR); }
|
||||
not
|
||||
{ RETURN(OP_NOT); }
|
||||
|
||||
":"
|
||||
{ RETURN(SU_COLON); }
|
||||
","
|
||||
{ RETURN(SU_COMMA); }
|
||||
"("
|
||||
{ RETURN(SU_POPEN); }
|
||||
")"
|
||||
{ RETURN(SU_PCLOSE); }
|
||||
";"
|
||||
{ RETURN(SU_EOC); }
|
||||
|
||||
A D D R E S S
|
||||
{ RETURN(RX_ADDRESS); }
|
||||
A R G
|
||||
{ RETURN(RX_ARG); }
|
||||
C A L L
|
||||
{ RETURN(RX_CALL); }
|
||||
D O
|
||||
{ RETURN(RX_DO); }
|
||||
D R O P
|
||||
{ RETURN(RX_DROP); }
|
||||
E L S E
|
||||
{ RETURN(RX_ELSE); }
|
||||
E N D
|
||||
{ RETURN(RX_END); }
|
||||
E X I T
|
||||
{ RETURN(RX_EXIT); }
|
||||
I F
|
||||
{ RETURN(RX_IF); }
|
||||
I N T E R P R E T
|
||||
{ RETURN(RX_INTERPRET); }
|
||||
I T E R A T E
|
||||
{ RETURN(RX_ITERATE); }
|
||||
L E A V E
|
||||
{ RETURN(RX_LEAVE); }
|
||||
N O P
|
||||
{ RETURN(RX_NOP); }
|
||||
N U M E R I C
|
||||
{ RETURN(RX_NUMERIC); }
|
||||
O P T I O N S
|
||||
{ RETURN(RX_OPTIONS); }
|
||||
O T H E R W I S E
|
||||
{ RETURN(RX_OTHERWISE); }
|
||||
P A R S E
|
||||
{ RETURN(RX_PARSE); }
|
||||
P R O C E D U R E
|
||||
{ RETURN(RX_PROCEDURE); }
|
||||
P U L L
|
||||
{ RETURN(RX_PULL); }
|
||||
P U S H
|
||||
{ RETURN(RX_PUSH); }
|
||||
Q U E U E
|
||||
{ RETURN(RX_QUEUE); }
|
||||
R E T U R N
|
||||
{ RETURN(RX_RETURN); }
|
||||
S A Y
|
||||
{ RETURN(RX_SAY); }
|
||||
S E L E C T
|
||||
{ RETURN(RX_SELECT); }
|
||||
S I G N A L
|
||||
{ RETURN(RX_SIGNAL); }
|
||||
T H E N
|
||||
{ RETURN(RX_THEN); }
|
||||
T R A C E
|
||||
{ RETURN(RX_TRACE); }
|
||||
W H E N
|
||||
{ RETURN(RX_WHEN); }
|
||||
O F F
|
||||
{ RETURN(RXS_OFF); }
|
||||
O N
|
||||
{ RETURN(RXS_ON); }
|
||||
B Y
|
||||
{ RETURN(RXS_BY); }
|
||||
D I G I T S
|
||||
{ RETURN(RXS_DIGITS); }
|
||||
E N G I N E E R I N G
|
||||
{ RETURN(RXS_ENGINEERING); }
|
||||
E R R O R
|
||||
{ RETURN(RXS_ERROR); }
|
||||
E X P O S E
|
||||
{ RETURN(RXS_EXPOSE); }
|
||||
F A I L U R E
|
||||
{ RETURN(RXS_FAILURE); }
|
||||
F O R
|
||||
{ RETURN(RXS_FOR); }
|
||||
F O R E V E R
|
||||
{ RETURN(RXS_FOREVER); }
|
||||
F O R M
|
||||
{ RETURN(RXS_FORM); }
|
||||
F U Z Z
|
||||
{ RETURN(RXS_FUZZ); }
|
||||
H A L T
|
||||
{ RETURN(RXS_HALT); }
|
||||
L I N E I N
|
||||
{ RETURN(RXS_LINEIN); }
|
||||
N A M E
|
||||
{ RETURN(RXS_NAME); }
|
||||
N O T R E A D Y
|
||||
{ RETURN(RXS_NOTREADY); }
|
||||
N O V A L U E
|
||||
{ RETURN(RXS_NOVALUE); }
|
||||
S C I E N T I F I C
|
||||
{ RETURN(RXS_SCIENTIFIC); }
|
||||
S O U R C E
|
||||
{ RETURN(RXS_SOURCE); }
|
||||
S Y N T A X
|
||||
{ RETURN(RXS_SYNTAX); }
|
||||
T O
|
||||
{ RETURN(RXS_TO); }
|
||||
U N T I L
|
||||
{ RETURN(RXS_UNTIL); }
|
||||
U P P E R
|
||||
{ RETURN(RXS_UPPER); }
|
||||
V A L U E
|
||||
{ RETURN(RXS_VALUE); }
|
||||
V A R
|
||||
{ RETURN(RXS_VAR); }
|
||||
V E R S I O N
|
||||
{ RETURN(RXS_VERSION); }
|
||||
W H I L E
|
||||
{ RETURN(RXS_WHILE); }
|
||||
W I T H
|
||||
{ RETURN(RXS_WITH); }
|
||||
|
||||
const
|
||||
{ RETURN(SU_CONST); }
|
||||
simple
|
||||
{ RETURN(SU_SYMBOL); }
|
||||
stem
|
||||
{ RETURN(SU_SYMBOL_STEM); }
|
||||
symbol
|
||||
{ RETURN(SU_SYMBOL_COMPOUND); }
|
||||
str
|
||||
{ RETURN(SU_LITERAL); }
|
||||
str [bB] / (all\symchr)
|
||||
{ RETURN(SU_LITERAL_BIN); }
|
||||
str [xX] / (all\symchr)
|
||||
{ RETURN(SU_LITERAL_HEX); }
|
||||
|
||||
eof
|
||||
{ RETURN(SU_EOF); }
|
||||
any
|
||||
{ RETURN(SU_ERROR); }
|
||||
*/
|
||||
}
|
||||
|
||||
bool StripToken(){
|
||||
uchar *cursor = ScanCB.cur;
|
||||
unsigned depth;
|
||||
uchar ch;
|
||||
bool blanks = FALSE;
|
||||
ScanCB.eot = cursor;
|
||||
strip:
|
||||
/*!re2c
|
||||
"/*"
|
||||
{
|
||||
depth = 1;
|
||||
goto comment;
|
||||
}
|
||||
"\r"
|
||||
{ goto strip; }
|
||||
[ \t]
|
||||
{
|
||||
blanks = TRUE;
|
||||
goto strip;
|
||||
}
|
||||
[] / all
|
||||
{ RETURN(blanks); }
|
||||
*/
|
||||
|
||||
comment:
|
||||
/*!re2c
|
||||
"*/"
|
||||
{
|
||||
if(--depth == 0)
|
||||
goto strip;
|
||||
else
|
||||
goto comment;
|
||||
}
|
||||
"\n"
|
||||
{
|
||||
++(ScanCB.lineNum);
|
||||
ScanCB.linePos = ScanCB.pos + (cursor - ScanCB.mrk);
|
||||
goto comment;
|
||||
}
|
||||
"/*"
|
||||
{
|
||||
++depth;
|
||||
goto comment;
|
||||
}
|
||||
eof
|
||||
{ RETURN(blanks); }
|
||||
any
|
||||
{
|
||||
goto comment;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
uchar *ScanFill(uchar *cursor){
|
||||
unsigned cnt = s->tok - s->bot;
|
||||
s->pos += cursor - s->mrk;
|
||||
if(cnt){
|
||||
if(s->eot){
|
||||
unsigned len = s->eot - s->tok;
|
||||
memcpy(s->bot, s->tok, len);
|
||||
s->eot = &s->bot[len];
|
||||
if((len = s->lim - cursor) != 0)
|
||||
memcpy(s->eot, cursor, len);
|
||||
cursor = s->eot;
|
||||
s->lim = &cursor[len];
|
||||
} else {
|
||||
memcpy(s->bot, s->tok, s->lim - s->tok);
|
||||
cursor -= cnt;
|
||||
s->lim -= cnt;
|
||||
}
|
||||
s->tok = s->bot;
|
||||
s->ptr -= cnt;
|
||||
}
|
||||
if((s->top - s->lim) < 512){
|
||||
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + 512)*sizeof(uchar));
|
||||
memcpy(buf, s->bot, s->lim - s->bot);
|
||||
s->tok = buf;
|
||||
s->ptr = &buf[s->ptr - s->bot];
|
||||
if(s->eot)
|
||||
s->eot = &buf[s->eot - s->bot];
|
||||
cursor = &buf[cursor - s->bot];
|
||||
s->lim = &buf[s->lim - s->bot];
|
||||
s->top = &s->lim[512];
|
||||
free(s->bot);
|
||||
s->bot = buf;
|
||||
}
|
||||
s->mrk = cursor;
|
||||
if(ScanCBIO.file){
|
||||
if((cnt = read(ScanCBIO.u.f.fd, (char*) s->lim, 512)) != 512)
|
||||
memset(&s->lim[cnt], 0, 512 - cnt);
|
||||
s->lim += 512;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/*!re2c
|
||||
"print" {return PRINT;}
|
||||
[a-z]+ {return ID;}
|
||||
[0-9]+ {return DEC;}
|
||||
"0x" [0-9a-f]+ {return HEX;}
|
||||
[\000-\377] {return ERR;}
|
||||
*/
|
||||
@@ -1,13 +0,0 @@
|
||||
#define NULL ((char*) 0)
|
||||
char *scan(char *p){
|
||||
char *q;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT p
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n)
|
||||
/*!re2c
|
||||
[0-9]+ {return YYCURSOR;}
|
||||
[\000-\377] {return NULL;}
|
||||
*/
|
||||
}
|
||||
@@ -1,706 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Manpage of RE2C</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>RE2C</h1>
|
||||
Section: User Commands (1)<br />
|
||||
Updated: @PACKAGE_DATE@<br />
|
||||
<a href="#index">Index</a>
|
||||
<hr />
|
||||
<a name="lbAB" id="lbAB"> </a>
|
||||
<h2>NAME</h2>
|
||||
<p>re2c - convert regular expressions to C/C++</p>
|
||||
<a name="lbAC" id="lbAC"> </a>
|
||||
<h2>SYNOPSIS</h2>
|
||||
<p><b>re2c</b> [<b>-bdefFghisuvVw1</b>] [<b>-o output</b>] [<b>-c</b> [<b>-t header</b>]] file</p>
|
||||
<a name="lbAD" id="lbAD"> </a>
|
||||
<h2>DESCRIPTION</h2>
|
||||
<p><b>re2c</b> is a preprocessor that generates C-based recognizers from
|
||||
regular expressions. The input to <b>re2c</b> consists of C/C++ source
|
||||
interleaved with comments of the form /*!re2c ... */ which contain scanner
|
||||
specifications. In the output these comments are replaced with code that, when
|
||||
executed, will find the next input token and then execute some user-supplied
|
||||
token-specific code.</p>
|
||||
<p>For example, given the following code</p>
|
||||
<pre>
|
||||
char *scan(char *p)
|
||||
{
|
||||
/*!re2c
|
||||
re2c:define:YYCTYPE = "unsigned char";
|
||||
re2c:define:YYCURSOR = p;
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:yych:conversion = 1;
|
||||
re2c:indent:top = 1;
|
||||
[0-9]+ {return p;}
|
||||
[^] {return (char*)0;}
|
||||
*/
|
||||
}
|
||||
</pre>
|
||||
<br />
|
||||
<br />
|
||||
<p><b>re2c -is</b> will generate</p>
|
||||
<pre>
|
||||
/* Generated by re2c on Sat Apr 16 11:40:58 1994 */
|
||||
char *scan(char *p)
|
||||
{
|
||||
{
|
||||
unsigned char yych;
|
||||
|
||||
yych = (unsigned char)*p;
|
||||
if(yych <= '/') goto yy4;
|
||||
if(yych >= ':') goto yy4;
|
||||
++p;
|
||||
yych = (unsigned char)*p;
|
||||
goto yy7;
|
||||
yy3:
|
||||
{return p;}
|
||||
yy4:
|
||||
++p;
|
||||
yych = (unsigned char)*p;
|
||||
{return char*)0;}
|
||||
yy6:
|
||||
++p;
|
||||
yych = (unsigned char)*p;
|
||||
yy7:
|
||||
if(yych <= '/') goto yy3;
|
||||
if(yych <= '9') goto yy6;
|
||||
goto yy3;
|
||||
}
|
||||
|
||||
}
|
||||
</pre>
|
||||
<br />
|
||||
<br />
|
||||
<p>You can place one /*!max:re2c */ comment that will output a "#define YYMAXFILL
|
||||
<n>" line that holds the maximum number of characters
|
||||
required to parse the input. That is the maximum value YYFILL(n)
|
||||
will receive. If -1 is in effect then YYMAXFILL can be triggered once
|
||||
after the last /*!re2c */.</p>
|
||||
<p>You can also use /*!ignore:re2c */ blocks that allows to document the
|
||||
scanner code and will not be part of the output.</p>
|
||||
<a name="lbAE" id="lbAE"> </a>
|
||||
<h2>OPTIONS</h2>
|
||||
<p><b>re2c</b> provides the following options:</p>
|
||||
<dl compact="compact">
|
||||
<dt><b>-?</b></dt>
|
||||
<dd><b>-h</b> Invoke a short help.<br /><br /></dd>
|
||||
<dt><b>-b</b></dt>
|
||||
<dd>Implies <b>-s</b>. Use bit vectors as well in the attempt to coax better
|
||||
code out of the compiler. Most useful for specifications with more than a few
|
||||
keywords (e.g. for most programming languages).<br /><br /></dd>
|
||||
<dt><b>-c</b></dt>
|
||||
<dd>Used to support (f)lex-like condition support.<br /><br /></dd>
|
||||
<dt><b>-d</b></dt>
|
||||
<dd>Creates a parser that dumps information about the current position and in
|
||||
which state the parser is while parsing the input. This is useful to debug
|
||||
parser issues and states. If you use this switch you need to define a macro
|
||||
<i>YYDEBUG</i> that is called like a function with two parameters: <i>void
|
||||
YYDEBUG(int state, char current)</i>. The first parameter receives the state or
|
||||
-1 and the second parameter receives the input at the current cursor.<br /><br /></dd>
|
||||
<dt><b>-D</b></dt>
|
||||
<dd>Emit Graphviz dot data. It can then be processed with e.g.
|
||||
"dot -Tpng input.dot > output.png". Please note that scanners with many states
|
||||
may crash dot.<br /><br /></dd>
|
||||
<dt><b>-e</b></dt>
|
||||
<dd>Cross-compile from an ASCII platform to an EBCDIC one.<br /><br /></dd>
|
||||
<dt><b>-f</b></dt>
|
||||
<dd>Generate a scanner with support for storable state. For details see below
|
||||
at <b>SCANNER WITH STORABLE STATES</b>.<br /><br /></dd>
|
||||
<dt><b>-F</b><dt>
|
||||
<dd>Partial support for flex syntax. When this flag is active then named
|
||||
definitions must be surrounded by curly braces and can be defined without an
|
||||
equal sign and the terminating semi colon. Instead names are treated as direct
|
||||
double quoted strings.<br /><br /></dd>
|
||||
<dt><b>-g</b></dt>
|
||||
<dd>Generate a scanner that utilizes GCC's computed goto feature. That is re2c
|
||||
generates jump tables whenever a decision is of a certain complexity (e.g. a
|
||||
lot of if conditions are otherwise necessary). This is only useable with GCC
|
||||
and produces output that cannot be compiled with any other compiler. Note that
|
||||
this implies -b and that the complexity threshold can be configured using the
|
||||
inplace configuration "cgoto:threshold".</dd>
|
||||
<dt><b>-i</b></dt>
|
||||
<dd>Do not output #line information. This is useful when you want use a CMS
|
||||
tool with the re2c output which you might want if you do not require your users
|
||||
to have re2c themselves when building from your source. <b>-o output</b>
|
||||
Specify the output file.<br /><br /></dd>
|
||||
<dt><b>-r</b></dt>
|
||||
<dd>Allows reuse of scanner definitions with '<b>/*!use:re2c</b>' after
|
||||
'<b>/*!rules:re2c</b>'. In this mode no '<b>/*!re2c</b>' block and exactly one
|
||||
'<b>/*!use:re2c</b>' must be present. The rules are being saved and used by
|
||||
every '<b>/*!repeat:re2c</b>' block that follows. These blocks can contain
|
||||
inplace configurations, especially '<b>re2c:flags:w</b>' and '<b>re2c:flags:u</b>'.
|
||||
That way it is possible to create the same scanner multiple times for different
|
||||
character types, different input mechanisms or different output mechanisms.
|
||||
The '<b>/*!use:re2c</b>' blocks can also contain additional rules that will be
|
||||
appended to the set of rules in '<b>/*!rules:re2c</b>'.
|
||||
<br /><br /></dd>
|
||||
<dt><b>-s</b></dt>
|
||||
<dd>Generate nested ifs for some switches. Many compilers need this assist to
|
||||
generate better code.<br /><br /></dd>
|
||||
<dt><b>-t</b></dt>
|
||||
<dd>Create a header file that contains types for the (f)lex-like condition support.
|
||||
This can only be activated when <b>-c</b> is in use.<br /><br /></dd>
|
||||
<dt><b>-u</b></dt>
|
||||
<dd>Generate a parser that supports Unicode chars (UTF-32). This means the
|
||||
generated code can deal with any valid Unicode character up to 0x10FFFF. When
|
||||
UTF-8 or UTF-16 needs to be supported you need to convert the incoming stream
|
||||
to UTF-32 upon input yourself.<br /><br /></dd>
|
||||
<dt><b>-v</b></dt>
|
||||
<dd>Show version information.<br /><br /></dd>
|
||||
<dt><b>-V</b></dt>
|
||||
<dd>Show the version as a number XXYYZZ.<br /><br /></dd>
|
||||
<dt><b>-w</b></dt>
|
||||
<dd>Create a parser that supports wide chars (UCS-2). This implies <b>-s</b>
|
||||
and cannot be used together with <b>-e</b> switch.<br /><br /></dd>
|
||||
<dt><b>-1</b></dt>
|
||||
<dd>Force single pass generation, this cannot be combined with -f and disables
|
||||
YYMAXFILL generation prior to last re2c block.<br /><br /></dd>
|
||||
<dt><b>--no-generation-date</b></dt>
|
||||
<dd>Suppress date output in the generated output so that it only shows the re2c
|
||||
version.<br /><br /></dd>
|
||||
<dt><b>--case-insensitive</b></dt>
|
||||
<dd>All strings are case insensitive, so all "-expressions are treated
|
||||
in the same way '-expressions are.<br /><br /></dd>
|
||||
<dt><b>--case-inverted</b></dt>
|
||||
<dd>Invert the meaning of single and double quoted strings.
|
||||
With this switch single quotes are case sensitive and
|
||||
double quotes are case insensitive.<br /><br /></dd>
|
||||
</dl>
|
||||
<br />
|
||||
<br />
|
||||
<a name="lbAF" id="lbAF"> </a>
|
||||
<h2>INTERFACE CODE</h2>
|
||||
<p>Unlike other scanner generators, <b>re2c</b> does not generate complete
|
||||
scanners: the user must supply some interface code. In particular, the user
|
||||
must define the following macros or use the
|
||||
corresponding inplace configurations:</p>
|
||||
<dl compact="compact">
|
||||
<dt>YYCONDTYPE</dt>
|
||||
<dd>In <b>-c</b> mode you can use <b>-t</b> to generate a file that contains the
|
||||
enumeration used as conditions. Each of the values refers to a condition of
|
||||
a rule set.</dd>
|
||||
<dt>YYCTXMARKER</dt>
|
||||
<dd><i>l</i>-expression of type *YYCTYPE. The generated code saves context
|
||||
backtracking information in YYCTXMARKER. The user only needs to define this
|
||||
macro if a scanner specification uses trailing context in one or more of its
|
||||
regular expressions.<br /><br /></dd>
|
||||
<dt>YYCTYPE</dt>
|
||||
<dd>Type used to hold an input symbol. Usually char or unsigned char.<br /><br /></dd>
|
||||
<dt>YYCURSOR</dt>
|
||||
<dd><i>l</i>-expression of type *YYCTYPE that points to the current input
|
||||
symbol. The generated code advances YYCURSOR as symbols are matched. On entry,
|
||||
YYCURSOR is assumed to point to the first character of the current token. On
|
||||
exit, YYCURSOR will point to the first character of the following token.<br /><br /></dd>
|
||||
<dt>YYDEBUG(<i>state</i>,<i>current</i>)</dt>
|
||||
<dd>This is only needed if the <b>-d</b> flag was specified. It allows to
|
||||
easily debug the generated parser by calling a user defined function for every
|
||||
state. The function should have the following signature: <i>void YYDEBUG(int
|
||||
state, char current)</i>. The first parameter receives the state or -1 and the
|
||||
second parameter receives the input at the current cursor.<br /><br /></dd>
|
||||
<dt>YYFILL(<i>n</i>)</dt>
|
||||
<dd>The generated code "calls" YYFILL(n) when the buffer needs (re)filling: at
|
||||
least <i>n</i> additional characters should be provided. YYFILL(n) should adjust
|
||||
YYCURSOR, YYLIMIT, YYMARKER and YYCTXMARKER as needed. Note that for typical
|
||||
programming languages <i>n</i> will be the length of the longest keyword plus
|
||||
one. The user can place a comment of the form /*!max:re2c */ once to insert
|
||||
a YYMAXFILL definition that is set to the maximum length value. If -1
|
||||
switch is used then YYMAXFILL can be triggered only once after the
|
||||
last /*!re2c */ block.<br /><br /></dd>
|
||||
<dt>YYGETCONDITION()</dt>
|
||||
<dd>This define is used to get the condition prior to entering the scanner code
|
||||
when using <b>-c</b> switch. The value must be initialized with a value from
|
||||
the enumeration YYCONDTYPE type.</dd>
|
||||
<dt>YYGETSTATE()</dt>
|
||||
<dd>The user only needs to define this macro if the <b>-f</b> flag was
|
||||
specified. In that case, the generated code "calls" YYGETSTATE() at the very
|
||||
beginning of the scanner in order to obtain the saved state. YYGETSTATE() must
|
||||
return a signed integer. The value must be either -1, indicating that the
|
||||
scanner is entered for the first time, or a value previously saved by
|
||||
YYSETSTATE(s). In the second case, the scanner will resume operations right after
|
||||
where the last YYFILL(n) was called.<br /><br /></dd>
|
||||
<dt>YYLIMIT</dt>
|
||||
<dd>Expression of type *YYCTYPE that marks the end of the buffer (YYLIMIT[-1] is
|
||||
the last character in the buffer). The generated code repeatedly compares
|
||||
YYCURSOR to YYLIMIT to determine when the buffer needs (re)filling.<br /><br /></dd>
|
||||
<dt>YYMARKER</dt>
|
||||
<dd><i>l</i>-expression of type *YYCTYPE. The generated code saves backtracking
|
||||
information in YYMARKER. Some easy scanners might not use this.<br /><br /></dd>
|
||||
<dt>YYMAXFILL</dt>
|
||||
<dd>This will be automatically defined by /*!max:re2c */ blocks as explained
|
||||
above.<br /><br /></dd>
|
||||
<dt>YYSETCONDITION(<i>c</i>)</dt>
|
||||
<dd>This define is used to set the condition in transition rules. This is only
|
||||
being used when <b>-c</b> is active and transition rules are being used.<br /><br /></dd>
|
||||
<dt>YYSETSTATE(<i>s</i>)</dt>
|
||||
<dd>The user only needs to define this macro if the <b>-f</b> flag was
|
||||
specified. In that case, the generated code "calls" YYSETSTATE just before
|
||||
calling YYFILL(n). The parameter to YYSETSTATE(s) is a signed integer that uniquely
|
||||
identifies the specific instance of YYFILL(n) that is about to be called. Should
|
||||
the user wish to save the state of the scanner and have YYFILL(n) return to the
|
||||
caller, all he has to do is store that unique identifier in a variable. Later,
|
||||
when the scanner is called again, it will call YYGETSTATE() and resume
|
||||
execution right where it left off. The generated code will contain
|
||||
both YYSETSTATE(s) and YYGETSTATE() even if YYFILL(n) is being
|
||||
disabled.<br /><br /></dd>
|
||||
</dl>
|
||||
<br />
|
||||
<br />
|
||||
<a name="lbAG" id="lbAG"> </a>
|
||||
<h2>SCANNER WITH STORABLE STATES</h2>
|
||||
<p>When the <b>-f</b> flag is specified, re2c generates a scanner that can
|
||||
store its current state, return to the caller, and later resume operations
|
||||
exactly where it left off.</p>
|
||||
<p>The default operation of re2c is a "pull" model, where the scanner asks for
|
||||
extra input whenever it needs it. However, this mode of operation assumes that
|
||||
the scanner is the "owner" the parsing loop, and that may not always be
|
||||
convenient.</p>
|
||||
<p>Typically, if there is a preprocessor ahead of the scanner in the stream, or
|
||||
for that matter any other procedural source of data, the scanner cannot "ask"
|
||||
for more data unless both scanner and source live in a separate threads.</p>
|
||||
<p>The <b>-f</b> flag is useful for just this situation : it lets users design
|
||||
scanners that work in a "push" model, i.e. where data is fed to the scanner
|
||||
chunk by chunk. When the scanner runs out of data to consume, it just stores
|
||||
its state, and return to the caller. When more input data is fed to the
|
||||
scanner, it resumes operations exactly where it left off.</p>
|
||||
<p>When using the -f option re2c does not accept stdin because it has to do the
|
||||
full generation process twice which means it has to read the input twice. That
|
||||
means re2c would fail in case it cannot open the input twice or reading the
|
||||
input for the first time influences the second read attempt.</p>
|
||||
<p>Changes needed compared to the "pull" model.</p>
|
||||
<p>1. User has to supply macros YYSETSTATE() and YYGETSTATE(state)</p>
|
||||
<p>2. The <b>-f</b> option inhibits declaration of <i>yych</i> and
|
||||
<i>yyaccept</i>. So the user has to declare these. Also the user has to save
|
||||
and restore these. In the example <i>examples/push.re</i> these are declared as
|
||||
fields of the (C++) class of which the scanner is a method, so they do not need
|
||||
to be saved/restored explicitly. For C they could e.g. be made macros that
|
||||
select fields from a structure passed in as parameter. Alternatively, they
|
||||
could be declared as local variables, saved with YYFILL(n) when it decides
|
||||
to return and restored at entry to the function. Also, it could be more
|
||||
efficient to save the state from YYFILL(n) because
|
||||
YYSETSTATE(state) is called unconditionally. YYFILL(n) however does not
|
||||
get <i>state</i> as parameter, so we would have to store state in a local
|
||||
variable by YYSETSTATE(state).</p>
|
||||
<p>3. Modify YYFILL(n) to return (from
|
||||
the function calling it) if more input is needed.</p>
|
||||
<p>4. Modify caller to recognise "more input is needed" and respond
|
||||
appropriately.</p>
|
||||
<p>5.The generated code will contain a switch block that is used to restores
|
||||
the last state by jumping behind the corresponding YYFILL(n) call. This code is
|
||||
automatically generated in the epilog of the first "/*!re2c */" block.
|
||||
It is possible to trigger generation of the YYGETSTATE() block earlier by
|
||||
placing a "/*!getstate:re2c */" comment. This is especially useful when
|
||||
the scanner code should be wrapped inside a loop.</p>
|
||||
<p>Please see examples/push.re for push-model scanner. The generated code can be
|
||||
tweaked using inplace configurations "state:abort" and "state:nextlabel".</p>
|
||||
<a name="lbAH" id="lbAH"> </a>
|
||||
<h2>SCANNER WITH CONDITION SUPPORT</h2>
|
||||
<p>
|
||||
You can precede regular-expressions with a list of condition names when using the <b>-c</b>
|
||||
switch. In this case <b>re2c</b> generates scanner blocks for each condition. Where each of the
|
||||
generated scanners has its own precondition. The precondition is given by the
|
||||
interface define <b>YYGETCONDITION</b> and must be of type <b>YYCONDTYPE</b>.
|
||||
</p><p>
|
||||
There are two special rule types. First, the rules of the condition '*' are
|
||||
merged to all conditions. And second the empty condition list allows to
|
||||
provide a code block that does not have a scanner part. Meaning it does not
|
||||
allow any regular expression. The condition value referring to this special
|
||||
block is always the one with the enumeration value 0. This way the code of this
|
||||
special rule can be used to initialize a scanner. It is in no way necessary to
|
||||
have these rules: but sometimes it is helpful to have a dedicated uninitialized
|
||||
condition state.
|
||||
</p><p>
|
||||
Non empty rules allow to specify the new condition, which makes them
|
||||
transition rules. Besides generating calls for the define <b>YYSETCONDITION</b>
|
||||
no other special code is generated.
|
||||
</p>
|
||||
<p>
|
||||
There is another kind of special rules that allow to prepend code to any code
|
||||
block of all rules of a certain set of conditions or to all code blocks to all
|
||||
rules. This can be helpful when some operation is common among rules. For
|
||||
instance this can be used to store the length of the scanned string. These
|
||||
special setup rules start with an exclamation mark followed by either a list
|
||||
of conditions <b><! condition, ... ></b> or a star <b><!*></b>.
|
||||
When <b>re2c</b> generates the code for a rule whose state does not have a
|
||||
setup rule and a star'd setup rule is present, than that code will be used
|
||||
as setup code.
|
||||
</p>
|
||||
<a name="lbAI" id="lbAI"> </a>
|
||||
<h2>SCANNER SPECIFICATIONS</h2>
|
||||
<p>Each scanner specification consists of a set of <i>rules</i>, <i>named
|
||||
definitions</i> and <i>configurations</i>.</p>
|
||||
<p><i>Rules</i> consist of a regular expression along with a block of C/C++
|
||||
code that is to be executed when the associated <i>regular expression</i> is
|
||||
matched. You can either
|
||||
start the code with an opening curly brace or the sequence '<b>:=</b>'. When
|
||||
the code with a curly brace then <b>re2c</b> counts the brace depth and stops looking
|
||||
for code automatically. Otherwise curly braces are not allowed and <b>re2c</b> stops
|
||||
looking for code at the first line that does not begin with whitespace.</p>
|
||||
<dl compact="compact">
|
||||
<dd><i>regular-expression</i> { <i>C/C++ code</i> }</dd>
|
||||
<dd><i>regular-expression</i> := <i>C/C++ code</i></dd>
|
||||
</dl>
|
||||
<p>
|
||||
If <b>-c</b> is active then each regular expression is preceded by a list of
|
||||
comma separated condition names. Besides normal naming rules there are two
|
||||
special cases. A rule may contain the single condition name '*' and no condition
|
||||
name at all. In the latter case the rule cannot have a regular expression. Non
|
||||
empty rules may further more specify the new condition. In that case re2c will
|
||||
generated the necessary code to change the condition automatically. Just as above
|
||||
code can be started with a curly brace of the sequence '<b>:=</b>'. Further more
|
||||
rules can use ':=>' as a shortcut to automatically generate code that not only
|
||||
sets the new condition state but also continues execution with the new state. A
|
||||
shortcut rule should not be used in a loop where there is code between the start
|
||||
of the loop and the <b>re2c</b> block unless <i>re2c:cond:goto</i> is changed
|
||||
to '<i>continue;</i>'. If code is necessary before all rule (though not simple
|
||||
jumps) you can do so by using <! pseudo-rules.
|
||||
</p>
|
||||
<dl compact="compact">
|
||||
<dd><<i>condition-list</i>> <i>regular-expression</i> { <i>C/C++ code</i> }</dd>
|
||||
<dd><<i>condition-list</i>> <i>regular-expression</i> := <i>C/C++ code</i></dd>
|
||||
<dd><<i>condition-list</i>> <i>regular-expression</i> => <i>condition</i> { <i>C/C++ code</i> }</dd>
|
||||
<dd><<i>condition-list</i>> <i>regular-expression</i> => <i>condition</i> := <i>C/C++ code</i></dd>
|
||||
<dd><<i>condition-list</i>> <i>regular-expression</i> :=> <i>condition</i></dd>
|
||||
<dd><<i>*</i>> <i>regular-expression</i> { <i>C/C++ code</i> }</dd>
|
||||
<dd><<i>*</i>> <i>regular-expression</i> := <i>C/C++ code</i></dd>
|
||||
<dd><<i>*</i>> <i>regular-expression</i> => <i>condition</i> { <i>C/C++ code</i> }</dd>
|
||||
<dd><<i>*</i>> <i>regular-expression</i> => <i>condition</i> := <i>C/C++ code</i></dd>
|
||||
<dd><<i>*</i>> <i>regular-expression</i> :=> <i>condition</i></dd>
|
||||
<dd><> { <i>C/C++ code</i> }</dd>
|
||||
<dd><> := <i>C/C++ code</i></dd>
|
||||
<dd><> => <i>condition</i> { <i>C/C++ code</i> }</dd>
|
||||
<dd><> => <i>condition</i> := <i>C/C++ code</i></dd>
|
||||
<dd><> :=> <i>condition</i></dd>
|
||||
<dd><!<i>condition-list</i>> { <i>C/C++ code</i> }</dd>
|
||||
<dd><!<i>condition-list</i>> := <i>C/C++ code</i></dd>
|
||||
<dd><!*> { <i>C/C++ code</i> }</dd>
|
||||
<dd><!*> := <i>C/C++ code</i></dd>
|
||||
</dl>
|
||||
<p>Named definitions are of the form:</p>
|
||||
<dl compact="compact">
|
||||
<dd><i>name</i> = <i>regular expression</i>;</dd>
|
||||
</dl>
|
||||
<p>When <b>-F</b> is active, then named definitions are also of the form:</p>
|
||||
<dl compact="compact">
|
||||
<dd><i>name</i> <i>regular expression</i></dd>
|
||||
</dl>
|
||||
<p>Configurations look like named definitions whose names start with
|
||||
"<b>re2c:</b>":</p>
|
||||
<dl compact="compact">
|
||||
<dd>re2c:<i>name</i> = <i>value</i>;</dd>
|
||||
<dd>re2c:<i>name</i> = <b>"</b><i>value</i><b>"</b>;</dd>
|
||||
</dl>
|
||||
<a name="lbAJ" id="lbAJ"> </a>
|
||||
<h2>SUMMARY OF RE2C REGULAR EXPRESSIONS</h2>
|
||||
<dl compact="compact">
|
||||
<dt>"foo"</dt>
|
||||
<dd>the literal string foo. ANSI-C escape sequences can be used.</dd>
|
||||
<dt>'foo'</dt>
|
||||
<dd>the literal string foo (characters [a-zA-Z] treated case-insensitive).
|
||||
ANSI-C escape sequences can be used.</dd>
|
||||
<dt>[xyz]</dt>
|
||||
<dd>a "character class"; in this case, the regular expression matches either an
|
||||
'x', a 'y', or a 'z'.</dd>
|
||||
<dt>[abj-oZ]</dt>
|
||||
<dd>a "character class" with a range in it; matches an 'a', a 'b', any letter
|
||||
from 'j' through 'o', or a 'Z'.</dd>
|
||||
<dt>[^<i>class</i>]</dt>
|
||||
<dd>an inverted "character class".</dd>
|
||||
<dt><i>r</i>\<i>s</i></dt>
|
||||
<dd>match any <i>r</i> which isn't an <i>s</i>. <i>r</i> and <i>s</i> must be
|
||||
regular expressions which can be expressed as character classes.</dd>
|
||||
<dt><i>r</i>*</dt>
|
||||
<dd>zero or more <i>r</i>'s, where <i>r</i> is any regular expression</dd>
|
||||
<dt><i>r</i>+</dt>
|
||||
<dd>one or more <i>r</i>'s</dd>
|
||||
<dt><i>r</i>?</dt>
|
||||
<dd>zero or one <i>r</i>'s (that is, "an optional <i>r</i>")</dd>
|
||||
<dt>name</dt>
|
||||
<dd>the expansion of the "named definition" (see above)</dd>
|
||||
<dt>(<i>r</i>)</dt>
|
||||
<dd>an <i>r</i>; parentheses are used to override precedence (see below)</dd>
|
||||
<dt><i>rs</i></dt>
|
||||
<dd>an <i>r</i> followed by an <i>s</i> ("concatenation")</dd>
|
||||
<dt><i>r</i>|<i>s</i></dt>
|
||||
<dd>either an <i>r</i> or an <i>s</i></dd>
|
||||
<dt><i>r</i>/<i>s</i></dt>
|
||||
<dd>an <i>r</i> but only if it is followed by an <i>s</i>. The <i>s</i> is not part of
|
||||
the matched text. This type of regular expression is called "trailing context". A trailing
|
||||
context can only be the end of a rule and not part of a named definition.</dd>
|
||||
<dt><i>r</i>{<i>n</i>}</dt>
|
||||
<dd>matches <i>r</i> exactly <i>n</i> times.</dd>
|
||||
<dt><i>r</i>{<i>n</i>,}</dt>
|
||||
<dd>matches <i>r</i> at least <i>n</i> times.</dd>
|
||||
<dt><i>r</i>{<i>n</i>,<i>m</i>}</dt>
|
||||
<dd>matches <i>r</i> at least <i>n</i> but not more than <i>m</i> times.</dd>
|
||||
<dt>.</dt>
|
||||
<dd>match any character except newline (\n).</dd>
|
||||
<dt><i>def</i></dt>
|
||||
<dd>matches named definition as specified by <i>def</i> only if <b>-F</b> is
|
||||
off. If the switch <b>-F</b> is active then this behaves like it was enclosed
|
||||
in double quotes and matches the string <i>def</i>.</dd>
|
||||
</dl>
|
||||
<br />
|
||||
<br />
|
||||
<p>Character classes and string literals may contain octal or hexadecimal
|
||||
character definitions and the following set of escape sequences
|
||||
(<b>\n</b>,<br />
|
||||
<b>\t</b>, <b>\v</b>, <b>\b</b>, <b>\r</b>, <b>\f</b>, <b>\a</b>, <b>\\</b>).
|
||||
An octal character is defined by a backslash followed by its three octal digits
|
||||
and a hexadecimal character is defined by backslash, a lower cased '<b>x</b>'
|
||||
and its two hexadecimal digits or a backslash, an upper cased <b>X</b> and its
|
||||
four hexadecimal digits.</p>
|
||||
<p>re2c further more supports the c/c++ unicode notation. That is a backslash
|
||||
followed by either a lowercased <b>u</b> and its four hexadecimal digits or an
|
||||
uppercased <b>U</b> and its eight hexadecimal digits. However only in \fB-u\fP
|
||||
mode the generated code can deal with any valid Unicode character up to
|
||||
0x10FFFF.</p>
|
||||
<p>Since characters greater <b>\X00FF</b> are not allowed in non unicode mode,
|
||||
the only portable "<b>any</b>" rules are <b>(.|"\n")</b> and <b>[^]</b>.</p>
|
||||
<p>The regular expressions listed above are grouped according to precedence,
|
||||
from highest precedence at the top to lowest at the bottom. Those grouped
|
||||
together have equal precedence.</p>
|
||||
<a name="lbAK" id="lbAK"> </a>
|
||||
<h2>INPLACE CONFIGURATION</h2>
|
||||
<p>It is possible to configure code generation inside re2c blocks. The
|
||||
following lists the available configurations:</p>
|
||||
<dl compact="compact">
|
||||
<dt><i>re2c:cond:divider</i> <b>=</b> "/* *********************************** */" <b>;</b></dt>
|
||||
<dd>Allows customizing of the divider for condition blocks. You can use '@@' to
|
||||
put the name of the condition or customize the placeholder
|
||||
using <i>re2c:cond:divider@cond</i>.</dd>
|
||||
<dt><i>re2c:cond:divider@cond</i> <b>=</b> @@ <b>;</b></dt>
|
||||
<dd>Specify the placeholder that will be replaced with the condition name
|
||||
in <i>re2c:cond:divider\fP</i>.</dd>
|
||||
<dt><i>re2c:cond:goto</i> <b>=</b> "goto @@;" <b>;</b></dt>
|
||||
<dd>Allows customizing of the conditional goto statements used with ':=>' style rules.
|
||||
You can use '@@' to put the name of the condition or customize the placeholder
|
||||
using <i>re2c:cond:goto@cond</i>. You can also change this to 'continue;',
|
||||
which would allow you to continue with the next loop cycle including any code
|
||||
between loop start and re2c block.</dd>
|
||||
<dt><i>re2c:cond:goto@cond</i> <b>=</b> @@ <b>;</b></dt>
|
||||
<dd>Specifies the placeholder that will be replaced with the condition label
|
||||
in <i>re2c:cond:goto</i>.</dd>
|
||||
<dt><i>re2c:indent:top</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>Specifies the minimum number of indentation to use. Requires a numeric
|
||||
value greater than or equal zero.</dd>
|
||||
<dt><i>re2c:condprefix</i> <b>=</b> yyc_ <b>;</b></dt>
|
||||
<dd>Allows to specify the prefix used for condition labels. That is this text is
|
||||
prepended to any condition label in the generated output file.</dd>
|
||||
<dt><i>re2c:condenumprefix</i> <b>=</b> yyc <b>;</b></dt>
|
||||
<dd>Allows to specify the prefix used for condition values. That is this text is
|
||||
prepended to any condition enum value in the generated output file.</dd>
|
||||
<dt><i>re2c:indent:string</i> <b>=</b> "\t" <b>;</b></dt>
|
||||
<dd>Specifies the string to use for indentation. Requires a string that should
|
||||
contain only whitespace unless you need this for external tools. The easiest
|
||||
way to specify spaces is to include them in single or double quotes. If you do
|
||||
not want any indentation at all you can simply set this to <b>""</b>.</dd>
|
||||
<dt><i>re2c:yych:conversion</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>When this setting is non zero, then \*(re automatically generates conversion
|
||||
code whenever yych gets read. In this case the type must be defined using
|
||||
<b>re2c:define:YYCTYPE</b>.</dd>
|
||||
<dt><i>re2c:yych:emit</i> <b>=</b> 1 <b>;</b></dt>
|
||||
<dd>Generation of \fByych\fP can be suppressed by setting this to 0.</dd>
|
||||
<dt><i>re2c:yybm:hex</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>If set to zero then a decimal table is being used else a hexadecimal table
|
||||
will be generated.</dd>
|
||||
<dt><i>re2c:yyfill:enable</i> <b>=</b> 1 <b>;</b></dt>
|
||||
<dd>Set this to zero to suppress generation of YYFILL(n). When using this be sure
|
||||
to verify that the generated scanner does not read behind input. Allowing
|
||||
this behavior might introduce sever security issues to you programs.</dd>
|
||||
<dt><i>re2c:yyfill:check</i> <b>=</b> 1 </b>;</b></dt>
|
||||
<dd>This can be set 0 to suppress output of the pre condition using YYCURSOR and
|
||||
YYLIMIT which becomes useful when YYLIMIT + max(YYFILL) is always accessible.</dd>
|
||||
<dt><i>re2c:yyfill:parameter</i> <b>=</b> 1 <b>;</b></dt>
|
||||
<dd>Allows to suppress parameter passing to <b>YYFILL</b> calls. If set to zero
|
||||
then no parameter is passed to <b>YYFILL</b>. However <b>define:YYFILL@LEN</b>
|
||||
allows to specify a replacement string for the actual length value. If set to
|
||||
a non zero value then <b>YYFILL</b> usage will be followed by the number of
|
||||
requested characters in braces unless <b>re2c:define:YYFILL:naked</b> is set.
|
||||
Also look at <b>re2c:define:YYFILL:naked</b> and <b>re2c:define:YYFILL@LEN</b>.</dd>
|
||||
<dt><i>re2c:startlabel</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>If set to a non zero integer then the start label of the next scanner
|
||||
blocks will be generated even if not used by the scanner itself. Otherwise the
|
||||
normal <b>yy0</b> like start label is only being generated if needed. If set to
|
||||
a text value then a label with that text will be generated regardless of
|
||||
whether the normal start label is being used or not. This setting is being
|
||||
reset to <b>0</b> after a start label has been generated.</dd>
|
||||
<dt><i>re2c:labelprefix</i> <b>=</b> yy <b>;</b></dt>
|
||||
<dd>Allows to change the prefix of numbered labels. The default is \fByy\fP and
|
||||
can be set any string that is a valid label.</dd>
|
||||
<dt><i>re2c:state:abort</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>When not zero and switch -f is active then the YYGETSTATE block will
|
||||
contain a default case that aborts and a -1 case is used for initialization.</dd>
|
||||
<dt><i>re2c:state:nextlabel</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>Used when -f is active to control whether the YYGETSTATE block is
|
||||
followed by a yyNext: label line. Instead of using yyNext you can
|
||||
usually also use configuration <i>startlabel</i> to force a specific start label
|
||||
or default to yy0 as start label. Instead of using a dedicated label it
|
||||
is often better to separate the YYGETSTATE code from the actual scanner code by
|
||||
placing a "/*!getstate:re2c */" comment.</dd>
|
||||
<dt><i>re2c:cgoto:threshold</i> <b>=</b> 9 <b>;</b></dt>
|
||||
<dd>When -g is active this value specifies the complexity threshold that triggers
|
||||
generation of jump tables rather than using nested if's and decision bitfields.
|
||||
The threshold is compared against a calculated estimation of if-s needed where
|
||||
every used bitmap divides the threshold by 2.</dd>
|
||||
<dt><i>re2c:yych:conversion</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>When the input uses signed characters and <b>-s</b> or <b>-b</b> switches are
|
||||
in effect re2c allows to automatically convert to the unsigned character type
|
||||
that is then necessary for its internal single character. When this setting
|
||||
is zero or an empty string the conversion is disabled. Using a non zero number
|
||||
the conversion is taken from <b>YYCTYPE</b>. If that is given by an inplace
|
||||
configuration that value is being used. Otherwise it will be <b>(YYCTYPE)</b>
|
||||
and changes to that configuration are no longer possible. When this setting is
|
||||
a string the braces must be specified. Now assuming your input is a <b>char*</b>
|
||||
buffer and you are using above mentioned switches you can set <b>YYCTYPE</b> to
|
||||
<b>unsigned char</b> and this setting to either <b>1</b> or <b>"(unsigned char)"</b>.</dd>
|
||||
<dt><i>re2c:define:define:YYCONDTYPE</i> <b>=</b> YYCONDTYPE <b>;</b></dt>
|
||||
<dd>Enumeration used for condition support with <b>-c</b> mode.</dd>
|
||||
<dt><i>re2c:define:YYCTXMARKER</i> <b>=</b> YYCTXMARKER <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define YYCTXMARKER and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYCTYPE</i> <b>=</b> YYCTYPE <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define YYCTYPE and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYCURSOR</i> <b>=</b> YYCURSOR <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define YYCURSOR and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYDEBUG</i> <b>=</b> YYDEBUG <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define \fBYYDEBUG\fP and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYFILL</i> <b>=</b> YYFILL <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define \fBYYFILL\fP and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYFILL:naked</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>When set to 1 neither braces, parameter nor semicolon gets emitted.</dd>
|
||||
<dt><i>re2c:define:YYFILL@LEN</i> <b>=</b> @@ <b>;</b></dt>
|
||||
<dd>When using <b>re2c:define:YYFILL</b> and <b>re2c:yyfill:parameter</b> is 0 then
|
||||
any occurrence of this text inside <b>YYFILL</b> will be replaced with the actual
|
||||
length value.</dd>
|
||||
<dt><i>re2c:define:YYGETCONDITION</i> <b>=</b> YYGETCONDITION <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define <b>YYGETCONDITION</b>.</dd>
|
||||
<dt><i>re2c:define:YYGETCONDITION:naked</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dd>When set to 1 neither braces, parameter nor semicolon gets emitted.</dd>
|
||||
<dt><i>re2c:define:YYGETSTATE</i> <b>=</b> YYGETSTATE <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define <b>YYGETSTATE</b> and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYGETSTATE:naked</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dt>When set to 1 neither braces, parameter nor semicolon gets emitted.</dt>
|
||||
<dt><i>re2c:define:YYLIMIT</i> <b>=</b> YYLIMIT <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define <b>YYLIMIT</b> and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYMARKER</i> <b>=</b> YYMARKER <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define <b>YYMARKER</b> and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYSETCONDITION</i> <b>=</b> YYSETCONDITION <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define <b>YYSETCONDITION</b>.</dd>
|
||||
<dt><i>re2c:define:YYSETCONDITION@cond</i> <b>=</b> @@ <b>;</b></dt>
|
||||
<dd>When using <b>re2c:define:YYSETCONDITION</b> then any occurrence of this text
|
||||
inside <b>YYSETCONDITION</b> will be replaced with the actual new condition value.</dd>
|
||||
<dt><i>re2c:define:YYSETSTATE</i> <b>=</b> YYSETSTATE <b>;</b></dt>
|
||||
<dd>Allows to overwrite the define <b>YYSETSTATE</b> and thus avoiding it by setting the
|
||||
value to the actual code needed.</dd>
|
||||
<dt><i>re2c:define:YYSETSTATE:naked</i> <b>=</b> 0 <b>;</b></dt>
|
||||
<dt>When set to 1 neither braces, parameter nor semicolon gets emitted.</dt>
|
||||
<dt><i>re2c:define:YYSETSTATE@state</i> <b>=</b> @@ <b>;</b></dt>
|
||||
<dd>When using <b>re2c:define:YYSETSTATE</b> then any occurrence of this text
|
||||
inside <b>YYSETSTATE</b> will be replaced with the actual new state value.</dd>
|
||||
<dt><i>re2c:label:yyFillLabel</i> <b>=</b> yyFillLabel <b>;</b></dt>
|
||||
<dd>Allows to overwrite the name of the label yyFillLabel.</dd>
|
||||
<dt><i>re2c:label:yyNext</i> <b>=</b> yyNext <b>;</b></dt>
|
||||
<dd>Allows to overwrite the name of the label yyNext.</dd>
|
||||
<dt><i>re2c:variable:yyaccept</i> <b>=</b> yyaccept <b>;</b></dt>
|
||||
<dd>Allows to overwrite the name of the variable yyaccept.</dd>
|
||||
<dt><i>re2c:variable:yybm</i> <b>=</b> yybm <b>;</b></dt>
|
||||
<dd>Allows to overwrite the name of the variable yybm.</dd>
|
||||
<dt><i>re2c:variable:yych</i> <b>=</b> yych <b>;</b></dt>
|
||||
<dd>Allows to overwrite the name of the variable yych.</dd>
|
||||
<dt><i>re2c:variable:yyctable</i> <b>=</b> yyctable <b>;</b></dt>
|
||||
<dd>When both <b>-c</b> and <b>-g</b> are active then <b>re2c</b> uses this variable to
|
||||
generate a static jump table for YYGETCONDITION.</dd>
|
||||
<dt><i>re2c:variable:yystable</i> <b>=</b> yystable <b>;</b></dt>
|
||||
<dd>When both <b>-f</b> and <b>-g</b> are active then <b>re2c</b> uses this variable to
|
||||
generate a static jump table for YYGETSTATE.</dd>
|
||||
<dt><i>re2c:variable:yytarget</i> <b>=</b> yytarget <b>;</b></dt>
|
||||
<dd>Allows to overwrite the name of the variable yytarget.</dd>
|
||||
</dl>
|
||||
<a name="lbAL" id="lbAL"> </a>
|
||||
<h2>UNDERSTANDING RE2C</h2>
|
||||
<p>The subdirectory lessons of the re2c distribution contains a few step by step
|
||||
lessons to get you started with re2c. All examples in the lessons subdirectory
|
||||
can be compiled and actually work.</p>
|
||||
<a name="lbAM" id="lbAM"> </a>
|
||||
<h2>FEATURES</h2>
|
||||
<p><b>re2c</b> does not provide a default action: the generated code assumes
|
||||
that the input will consist of a sequence of tokens. Typically this can be
|
||||
dealt with by adding a rule such as the one for unexpected characters in the
|
||||
example above.</p>
|
||||
<p>The user must arrange for a sentinel token to appear at the end of input
|
||||
(and provide a rule for matching it): <b>re2c</b> does not provide an
|
||||
<<EOF>> expression. If the source is from a null-byte terminated
|
||||
string, a rule matching a null character will suffice. If the source is from a
|
||||
file then you could pad the input with a newline (or some other character that
|
||||
cannot appear within another token); upon recognizing such a character check
|
||||
to see if it is the sentinel and act accordingly. And you can also use YYFILL(n)
|
||||
to end the scanner in case not enough characters are available which is nothing
|
||||
else then e detection of end of data/file.</p>
|
||||
<a name="lbAN" id="lbAN"> </a>
|
||||
<h2>BUGS</h2>
|
||||
<p>Difference only works for character sets.</p>
|
||||
<p>The <b>re2c</b> internal algorithms need documentation.</p>
|
||||
<a name="lbAO" id="lbAO"> </a>
|
||||
<h2>SEE ALSO</h2>
|
||||
<p>flex(1), lex(1). More information on <b>re2c</b> can be found here:
|
||||
<b><a href=
|
||||
"http://re2c.org/">http://re2c.org/</a></b></p>
|
||||
<a name="lbAP" id="lbAP"> </a>
|
||||
<h2>AUTHORS</h2>
|
||||
<ul>
|
||||
<li>Peter Bumbulis <<a href=
|
||||
"mailto:peter@csg.uwaterloo.ca">peter@csg.uwaterloo.ca</a>></li>
|
||||
<li>Brian Young <<a href=
|
||||
"mailto:bayoung@acm.org">bayoung@acm.org</a>></li>
|
||||
<li>Dan Nuffer <<a href=
|
||||
"mailto:nuffer@users.sourceforge.net">nuffer@users.sourceforge.net</a>></li>
|
||||
<li>Marcus Boerger <<a href=
|
||||
"mailto:helly@users.sourceforge.net">helly@users.sourceforge.net</a>></li>
|
||||
<li>Hartmut Kaiser <<a href=
|
||||
"mailto:hkaiser@users.sourceforge.net">hkaiser@users.sourceforge.net</a>></li>
|
||||
<li>Emmanuel Mogenet <<a href="mailto:mgix@mgix.com">mgix@mgix.com</a>>
|
||||
(added storable state)</li>
|
||||
</ul>
|
||||
<br />
|
||||
<br />
|
||||
<a name="lbAQ" id="lbAQ"> </a>
|
||||
<h2>VERSION INFORMATION</h2>
|
||||
<p>This manpage describes <b>re2c</b>, version @PACKAGE_VERSION@.</p>
|
||||
<hr />
|
||||
<a name="index" id="index"> </a>
|
||||
<h2>Index</h2>
|
||||
<dl>
|
||||
<dt><a href="#lbAB">NAME</a><br /></dt>
|
||||
<dt><a href="#lbAC">SYNOPSIS</a><br /></dt>
|
||||
<dt><a href="#lbAD">DESCRIPTION</a><br /></dt>
|
||||
<dt><a href="#lbAE">OPTIONS</a><br /></dt>
|
||||
<dt><a href="#lbAF">INTERFACE CODE</a><br /></dt>
|
||||
<dt><a href="#lbAG">SCANNER WITH STORABLE STATES</a><br /></dt>
|
||||
<dt><a href="#lbAH">SCANNER WITH CONDITION SUPPORT</a><br /></dt>
|
||||
<dt><a href="#lbAI">SCANNER SPECIFICATIONS</a><br /></dt>
|
||||
<dt><a href="#lbAJ">SUMMARY OF RE2C REGULAR EXPRESSIONS</a><br /></dt>
|
||||
<dt><a href="#lbAK">INPLACE CONFIGURATION</a><br /></dt>
|
||||
<dt><a href="#lbAL">UNDERSTANDING RE2C</a><br /></dt>
|
||||
<dt><a href="#lbAM">FEATURES</a><br /></dt>
|
||||
<dt><a href="#lbAN">BUGS</a><br /></dt>
|
||||
<dt><a href="#lbAO">SEE ALSO</a><br /></dt>
|
||||
<dt><a href="#lbAP">AUTHORS</a><br /></dt>
|
||||
<dt><a href="#lbAQ">VERSION INFORMATION</a><br /></dt>
|
||||
</dl>
|
||||
<br />
|
||||
<br />
|
||||
<hr />
|
||||
<p>This document was created by man2html, using the manual pages.<br />
|
||||
Date: @PACKAGE_DATE@</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,148 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "calc_001.re"
|
||||
/* re2c lesson 001_upn_calculator, calc_001, (c) M. Boerger 2006 - 2007 */
|
||||
#line 43 "calc_001.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int scan(char *s, int l)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = 0;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n)
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
#line 24 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy10;
|
||||
case '+': goto yy6;
|
||||
case '-': goto yy8;
|
||||
case '0': goto yy2;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy4;
|
||||
default: goto yy12;
|
||||
}
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
switch ((yych = *YYCURSOR)) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy16;
|
||||
default: goto yy3;
|
||||
}
|
||||
yy3:
|
||||
#line 64 "calc_001.re"
|
||||
{ printf("Num\n"); continue; }
|
||||
#line 64 "<stdout>"
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy15;
|
||||
yy5:
|
||||
#line 63 "calc_001.re"
|
||||
{ printf("Num\n"); continue; }
|
||||
#line 72 "<stdout>"
|
||||
yy6:
|
||||
++YYCURSOR;
|
||||
#line 65 "calc_001.re"
|
||||
{ printf("+\n"); continue; }
|
||||
#line 77 "<stdout>"
|
||||
yy8:
|
||||
++YYCURSOR;
|
||||
#line 66 "calc_001.re"
|
||||
{ printf("-\n"); continue; }
|
||||
#line 82 "<stdout>"
|
||||
yy10:
|
||||
++YYCURSOR;
|
||||
#line 67 "calc_001.re"
|
||||
{ printf("EOF\n"); return 0; }
|
||||
#line 87 "<stdout>"
|
||||
yy12:
|
||||
++YYCURSOR;
|
||||
#line 68 "calc_001.re"
|
||||
{ printf("ERR\n"); return 1; }
|
||||
#line 92 "<stdout>"
|
||||
yy14:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy15:
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy14;
|
||||
default: goto yy5;
|
||||
}
|
||||
yy16:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy16;
|
||||
default: goto yy18;
|
||||
}
|
||||
yy18:
|
||||
#line 62 "calc_001.re"
|
||||
{ printf("Oct\n"); continue; }
|
||||
#line 131 "<stdout>"
|
||||
}
|
||||
#line 69 "calc_001.re"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(argv[1], strlen(argv[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, calc_001, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- basic interface for string reading
|
||||
|
||||
. We define the macros YYCTYPE, YYCURSOR, YYLIMIT, YYMARKER, YYFILL
|
||||
. YYCTYPE is the type re2c operates on or in other words the type that
|
||||
it generates code for. While it is not a big difference when we were
|
||||
using 'unsigned char' here we would need to run re2c with option -w
|
||||
to fully support types with sieof() > 1.
|
||||
. YYCURSOR is used internally and holds the current scanner position. In
|
||||
expression handlers, the code blocks after re2c expressions, this can be
|
||||
used to identify the end of the token.
|
||||
. YYMARKER is not always being used so we set an initial value to avoid
|
||||
a compiler warning. Here we could also omit it compleley.
|
||||
. YYLIMIT stores the end of the input. Unfortunatley we have to use strlen()
|
||||
in this lesson. In the next example we see one way to get rid of it.
|
||||
. We use a 'for(;;)'-loop around the scanner block. We could have used a
|
||||
'while(1)'-loop instead but some compilers generate a warning for it.
|
||||
. To make the output more readable we use 're2c:indent:top' scanner
|
||||
configuration that configures re2c to prepend a single tab (the default)
|
||||
to the beginning of each output line.
|
||||
. The following lines are expressions and for each expression we output the
|
||||
token name and continue the scanner loop.
|
||||
. The second last token detects the end of our input, the terminating zero in
|
||||
our input string. In other scanners detecting the end of input may vary.
|
||||
For example binary code may contain \0 as valid input.
|
||||
. The last expression accepts any input character. It tells re2c to accept
|
||||
the opposit of the empty range. This includes numbers and our tokens but
|
||||
as re2c goes from top to botton when evaluating the expressions this is no
|
||||
problem.
|
||||
. The first three rules show that re2c actually prioritizes the expressions
|
||||
from top to bottom. Octal number require a starting "0" and the actual
|
||||
number. Normal numbers start with a digit greater 0. And zero is finally a
|
||||
special case. A single "0" is detected by the last rule of this set. And
|
||||
valid ocal number is already being detected by the first rule. This even
|
||||
includes multi "0" sequences that in octal notation also means zero.
|
||||
Another way would be to only use two rules:
|
||||
"0" [0-9]+
|
||||
"0" | ( [1-9] [0-9]* )
|
||||
A full description of re2c rule syntax can be found in the manual.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int scan(char *s, int l)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = 0;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n)
|
||||
|
||||
for(;;)
|
||||
{
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
"0"[0-9]+ { printf("Oct\n"); continue; }
|
||||
[1-9][0-9]* { printf("Num\n"); continue; }
|
||||
"0" { printf("Num\n"); continue; }
|
||||
"+" { printf("+\n"); continue; }
|
||||
"-" { printf("-\n"); continue; }
|
||||
"\000" { printf("EOF\n"); return 0; }
|
||||
[^] { printf("ERR\n"); return 1; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(argv[1], strlen(argv[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "calc_002.re"
|
||||
/* re2c lesson 001_upn_calculator, calc_002, (c) M. Boerger 2006 - 2007 */
|
||||
#line 19 "calc_002.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int fill(char *p, int n, char **l)
|
||||
{
|
||||
while (*++p && n--) ;
|
||||
* l = p;
|
||||
return n <= 0;
|
||||
}
|
||||
|
||||
int scan(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
char *l = s;
|
||||
char *q = 0;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT l
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n) { if (!fill(p, n, &l)) break; }
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
#line 32 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy10;
|
||||
case '+': goto yy6;
|
||||
case '-': goto yy8;
|
||||
case '0': goto yy2;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy4;
|
||||
default: goto yy12;
|
||||
}
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
switch ((yych = *YYCURSOR)) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy16;
|
||||
default: goto yy3;
|
||||
}
|
||||
yy3:
|
||||
#line 48 "calc_002.re"
|
||||
{ printf("Num\n"); continue; }
|
||||
#line 72 "<stdout>"
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy15;
|
||||
yy5:
|
||||
#line 47 "calc_002.re"
|
||||
{ printf("Num\n"); continue; }
|
||||
#line 80 "<stdout>"
|
||||
yy6:
|
||||
++YYCURSOR;
|
||||
#line 49 "calc_002.re"
|
||||
{ printf("+\n"); continue; }
|
||||
#line 85 "<stdout>"
|
||||
yy8:
|
||||
++YYCURSOR;
|
||||
#line 50 "calc_002.re"
|
||||
{ printf("+\n"); continue; }
|
||||
#line 90 "<stdout>"
|
||||
yy10:
|
||||
++YYCURSOR;
|
||||
#line 51 "calc_002.re"
|
||||
{ printf("EOF\n"); return 0; }
|
||||
#line 95 "<stdout>"
|
||||
yy12:
|
||||
++YYCURSOR;
|
||||
#line 52 "calc_002.re"
|
||||
{ printf("ERR\n"); return 1; }
|
||||
#line 100 "<stdout>"
|
||||
yy14:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy15:
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy14;
|
||||
default: goto yy5;
|
||||
}
|
||||
yy16:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy16;
|
||||
default: goto yy18;
|
||||
}
|
||||
yy18:
|
||||
#line 46 "calc_002.re"
|
||||
{ printf("Oct\n"); continue; }
|
||||
#line 139 "<stdout>"
|
||||
}
|
||||
#line 53 "calc_002.re"
|
||||
|
||||
}
|
||||
printf("OOD\n"); return 2;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, calc_002, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- making use of YYFILL
|
||||
|
||||
. Here we modified the scanner to not require strlen() on the call. Instead
|
||||
we compute limit on the fly. That is whenever more input is needed we
|
||||
search for the terminating \0 in the next n chars the scanner needs.
|
||||
. If there is not enough input we quit the scanner.
|
||||
. Note that in lesson_001 YYLIMIT was a character pointer computed only once.
|
||||
Here is of course also of type YYCTYPE but a variable that gets reevaluated
|
||||
by YYFILL().
|
||||
. To make the code smaller we take advantage of the fact that our loop has no
|
||||
break so far. This allows us to use break here and have the code that is
|
||||
used for YYFILL() not contain the printf in every occurrence. That way the
|
||||
generated code gets smaller.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int fill(char *p, int n, char **l)
|
||||
{
|
||||
while (*++p && n--) ;
|
||||
* l = p;
|
||||
return n <= 0;
|
||||
}
|
||||
|
||||
int scan(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
char *l = s;
|
||||
char *q = 0;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT l
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n) { if (!fill(p, n, &l)) break; }
|
||||
|
||||
for(;;)
|
||||
{
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
"0"[0-9]+ { printf("Oct\n"); continue; }
|
||||
[1-9][0-9]* { printf("Num\n"); continue; }
|
||||
"0" { printf("Num\n"); continue; }
|
||||
"+" { printf("+\n"); continue; }
|
||||
"-" { printf("+\n"); continue; }
|
||||
"\000" { printf("EOF\n"); return 0; }
|
||||
[^] { printf("ERR\n"); return 1; }
|
||||
*/
|
||||
}
|
||||
printf("OOD\n"); return 2;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "calc_003.re"
|
||||
/* re2c lesson 001_upn_calculator, calc_003, (c) M. Boerger 2006 - 2007 */
|
||||
#line 19 "calc_003.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int scan(char *s, int l)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = 0;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l+2)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n) { printf("OOD\n"); return 2; }
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
#line 24 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy10;
|
||||
case '+': goto yy6;
|
||||
case '-': goto yy8;
|
||||
case '0': goto yy2;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy4;
|
||||
default: goto yy12;
|
||||
}
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
switch ((yych = *YYCURSOR)) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy16;
|
||||
default: goto yy3;
|
||||
}
|
||||
yy3:
|
||||
#line 40 "calc_003.re"
|
||||
{ printf("Num\n"); continue; }
|
||||
#line 64 "<stdout>"
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy15;
|
||||
yy5:
|
||||
#line 39 "calc_003.re"
|
||||
{ printf("Num\n"); continue; }
|
||||
#line 72 "<stdout>"
|
||||
yy6:
|
||||
++YYCURSOR;
|
||||
#line 41 "calc_003.re"
|
||||
{ printf("+\n"); continue; }
|
||||
#line 77 "<stdout>"
|
||||
yy8:
|
||||
++YYCURSOR;
|
||||
#line 42 "calc_003.re"
|
||||
{ printf("+\n"); continue; }
|
||||
#line 82 "<stdout>"
|
||||
yy10:
|
||||
++YYCURSOR;
|
||||
#line 43 "calc_003.re"
|
||||
{ printf("EOF\n"); return 0; }
|
||||
#line 87 "<stdout>"
|
||||
yy12:
|
||||
++YYCURSOR;
|
||||
#line 44 "calc_003.re"
|
||||
{ printf("ERR\n"); return 1; }
|
||||
#line 92 "<stdout>"
|
||||
yy14:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy15:
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy14;
|
||||
default: goto yy5;
|
||||
}
|
||||
yy16:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy16;
|
||||
default: goto yy18;
|
||||
}
|
||||
yy18:
|
||||
#line 38 "calc_003.re"
|
||||
{ printf("Oct\n"); continue; }
|
||||
#line 131 "<stdout>"
|
||||
}
|
||||
#line 45 "calc_003.re"
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(argv[1], strlen(argv[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, calc_003, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- making use of YYFILL
|
||||
|
||||
. Again provide the length of the input to generate the limit only once. Now
|
||||
we can use YYFILL() to detect the end and simply return since YYFILL() is
|
||||
only being used if the next scanner run might use more chars then YYLIMIT
|
||||
allows.
|
||||
. Note that we now use (s+l+2) instead of (s+l) as we did in lesson_001. In
|
||||
the first lesson we did not quit from YYFILL() and used a special rule to
|
||||
detect the end of input. Here we use the fact that we know the exact end
|
||||
of input and that this length does not include the terminating zero. Since
|
||||
YYLIMIT points to the first character behind the used buffer we use "+ 2".
|
||||
If we would use "+1" we could drop the "\000" rule but could no longer
|
||||
distinguish between end of input and out of data.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int scan(char *s, int l)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = 0;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l+2)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n) { printf("OOD\n"); return 2; }
|
||||
|
||||
for(;;)
|
||||
{
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
"0"[0-9]+ { printf("Oct\n"); continue; }
|
||||
[1-9][0-9]* { printf("Num\n"); continue; }
|
||||
"0" { printf("Num\n"); continue; }
|
||||
"+" { printf("+\n"); continue; }
|
||||
"-" { printf("+\n"); continue; }
|
||||
"\000" { printf("EOF\n"); return 0; }
|
||||
[^] { printf("ERR\n"); return 1; }
|
||||
*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(argv[1], strlen(argv[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "calc_004.re"
|
||||
/* re2c lesson 001_upn_calculator, calc_004, (c) M. Boerger 2006 - 2007 */
|
||||
#line 20 "calc_004.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char * tokendup(const char *t, const char *l)
|
||||
{
|
||||
size_t n = l -t + 1;
|
||||
char *r = (char*)malloc(n);
|
||||
|
||||
memmove(r, t, n-1);
|
||||
r[n] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
||||
int scan(char *s, int l)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = 0;
|
||||
char *t;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l+2)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n) { printf("OOD\n"); return 2; }
|
||||
|
||||
for(;;)
|
||||
{
|
||||
t = p;
|
||||
|
||||
#line 36 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case 0x00: goto yy9;
|
||||
case '+': goto yy5;
|
||||
case '-': goto yy7;
|
||||
case '0': goto yy2;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy4;
|
||||
default: goto yy11;
|
||||
}
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
switch ((yych = *YYCURSOR)) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy15;
|
||||
default: goto yy3;
|
||||
}
|
||||
yy3:
|
||||
#line 57 "calc_004.re"
|
||||
{ t = tokendup(t, p); printf("Num: %s\n", t); free(t); continue; }
|
||||
#line 76 "<stdout>"
|
||||
yy4:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy14;
|
||||
yy5:
|
||||
++YYCURSOR;
|
||||
#line 58 "calc_004.re"
|
||||
{ printf("+\n"); continue; }
|
||||
#line 84 "<stdout>"
|
||||
yy7:
|
||||
++YYCURSOR;
|
||||
#line 59 "calc_004.re"
|
||||
{ printf("+\n"); continue; }
|
||||
#line 89 "<stdout>"
|
||||
yy9:
|
||||
++YYCURSOR;
|
||||
#line 60 "calc_004.re"
|
||||
{ printf("EOF\n"); return 0; }
|
||||
#line 94 "<stdout>"
|
||||
yy11:
|
||||
++YYCURSOR;
|
||||
#line 61 "calc_004.re"
|
||||
{ printf("ERR\n"); return 1; }
|
||||
#line 99 "<stdout>"
|
||||
yy13:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy14:
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy13;
|
||||
default: goto yy3;
|
||||
}
|
||||
yy15:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy15;
|
||||
default: goto yy17;
|
||||
}
|
||||
yy17:
|
||||
#line 56 "calc_004.re"
|
||||
{ t = tokendup(t, p); printf("Oct: %s\n", t); free(t); continue; }
|
||||
#line 138 "<stdout>"
|
||||
}
|
||||
#line 62 "calc_004.re"
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(argv[1], strlen(argv[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, calc_004, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- making use of definitions
|
||||
. We provide complex rules as definitions. We can even have definitions made
|
||||
up from other definitions. And we could also use definitions as part of
|
||||
rules and not only as full rules as shown in this lesson.
|
||||
|
||||
- showing the tokens
|
||||
. re2c does not store the beginning of a token on its own but we can easily
|
||||
do this by providing variable, in our case t, that is set to YYCURSOR on
|
||||
every loop. If we were not using a loop here the token, we could have used
|
||||
s instead of a new variable instead.
|
||||
. As we use the token for an output function that requires a terminating zero
|
||||
we copy the token. Alternatively we could store the end of the token, then
|
||||
replace it with a zero character and replace it after the token has been
|
||||
used. However that approach is not always acceptable.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char * tokendup(const char *t, const char *l)
|
||||
{
|
||||
size_t n = l -t + 1;
|
||||
char *r = (char*)malloc(n);
|
||||
|
||||
memmove(r, t, n-1);
|
||||
r[n] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
||||
int scan(char *s, int l)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = 0;
|
||||
char *t;
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l+2)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n) { printf("OOD\n"); return 2; }
|
||||
|
||||
for(;;)
|
||||
{
|
||||
t = p;
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
|
||||
DIGIT = [0-9] ;
|
||||
OCT = "0" DIGIT+ ;
|
||||
INT = "0" | ( [1-9] DIGIT* ) ;
|
||||
|
||||
OCT { t = tokendup(t, p); printf("Oct: %s\n", t); free(t); continue; }
|
||||
INT { t = tokendup(t, p); printf("Num: %s\n", t); free(t); continue; }
|
||||
"+" { printf("+\n"); continue; }
|
||||
"-" { printf("+\n"); continue; }
|
||||
"\000" { printf("EOF\n"); return 0; }
|
||||
[^] { printf("ERR\n"); return 1; }
|
||||
*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(argv[1], strlen(argv[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "calc_005.re"
|
||||
/* re2c lesson 001_upn_calculator, calc_005, (c) M. Boerger 2006 - 2007 */
|
||||
#line 19 "calc_005.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG(stmt) stmt
|
||||
|
||||
int stack[4];
|
||||
int depth = 0;
|
||||
|
||||
int push_num(const char *t, const char *l, int radix)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (depth >= sizeof(stack))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
--t;
|
||||
while(++t < l)
|
||||
{
|
||||
num = num * radix + (*t - '0');
|
||||
}
|
||||
DEBUG(printf("Num: %d\n", num));
|
||||
|
||||
stack[depth++] = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_add()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] + stack[depth];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_sub()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] - stack[depth];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan(char *s, int l)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = 0;
|
||||
char *t;
|
||||
int res = 0;
|
||||
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l+1)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n) { return depth == 1 ? 0 : 2; }
|
||||
|
||||
while(!res)
|
||||
{
|
||||
t = p;
|
||||
|
||||
#line 71 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '\t':
|
||||
case ' ': goto yy2;
|
||||
case '+': goto yy7;
|
||||
case '-': goto yy9;
|
||||
case '0': goto yy4;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy6;
|
||||
default: goto yy11;
|
||||
}
|
||||
yy2:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy19;
|
||||
yy3:
|
||||
#line 91 "calc_005.re"
|
||||
{ continue; }
|
||||
#line 101 "<stdout>"
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
switch ((yych = *YYCURSOR)) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy15;
|
||||
default: goto yy5;
|
||||
}
|
||||
yy5:
|
||||
#line 93 "calc_005.re"
|
||||
{ res = push_num(t, p, 10); continue; }
|
||||
#line 120 "<stdout>"
|
||||
yy6:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy14;
|
||||
yy7:
|
||||
++YYCURSOR;
|
||||
#line 94 "calc_005.re"
|
||||
{ res = stack_add(); continue; }
|
||||
#line 128 "<stdout>"
|
||||
yy9:
|
||||
++YYCURSOR;
|
||||
#line 95 "calc_005.re"
|
||||
{ res = stack_sub(); continue; }
|
||||
#line 133 "<stdout>"
|
||||
yy11:
|
||||
++YYCURSOR;
|
||||
#line 96 "calc_005.re"
|
||||
{ res = 1; continue; }
|
||||
#line 138 "<stdout>"
|
||||
yy13:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy14:
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy13;
|
||||
default: goto yy5;
|
||||
}
|
||||
yy15:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
switch (yych) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': goto yy15;
|
||||
default: goto yy17;
|
||||
}
|
||||
yy17:
|
||||
#line 92 "calc_005.re"
|
||||
{ res = push_num(t, p, 8); continue; }
|
||||
#line 177 "<stdout>"
|
||||
yy18:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy19:
|
||||
switch (yych) {
|
||||
case '\t':
|
||||
case ' ': goto yy18;
|
||||
default: goto yy3;
|
||||
}
|
||||
}
|
||||
#line 97 "calc_005.re"
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
char *inp;
|
||||
int res = 0, argp = 0, len;
|
||||
|
||||
while(!res && ++argp < argc)
|
||||
{
|
||||
inp = argv[argp];
|
||||
len = strlen(inp);
|
||||
if (inp[0] == '\"' && inp[len-1] == '\"')
|
||||
{
|
||||
++inp;
|
||||
len -=2;
|
||||
}
|
||||
res = scan(inp, len);
|
||||
}
|
||||
switch(res)
|
||||
{
|
||||
case 0:
|
||||
printf("Result: %d\n", stack[0]);
|
||||
return 0;
|
||||
case 1:
|
||||
fprintf(stderr, "Illegal character in input.\n");
|
||||
return 1;
|
||||
case 2:
|
||||
fprintf(stderr, "Premature end of input.\n");
|
||||
return 2;
|
||||
case 3:
|
||||
fprintf(stderr, "Stack overflow.\n");
|
||||
return 3;
|
||||
case 4:
|
||||
fprintf(stderr, "Stack underflow.\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, calc_005, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- turning this lesson into an easy calculator
|
||||
. We are going to write an UPN calculator so we need an additional rule to
|
||||
ignore white space.
|
||||
. Then we need to store the scanned input somewhere and do our math on it.
|
||||
. Also we need to scan all arguments since the main c code gets the input
|
||||
split up into chunks.
|
||||
. In contrast to what we did before we now add a variable res that holds the
|
||||
scanner state. We initialize that variable to 0 and quit the loop when it
|
||||
is non zero. This will also be our return value so that we can use it in
|
||||
function main to generate error information.
|
||||
. To support operating systems where ' and " get passed in program arguments
|
||||
we check for them being first and last input character. If so we correct
|
||||
input pointer and input length. Since now our scanner might not see a
|
||||
terminating zero we change YYLIMIT again and drop the special zero rule.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG(stmt) stmt
|
||||
|
||||
int stack[4];
|
||||
int depth = 0;
|
||||
|
||||
int push_num(const char *t, const char *l, int radix)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (depth >= sizeof(stack))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
--t;
|
||||
while(++t < l)
|
||||
{
|
||||
num = num * radix + (*t - '0');
|
||||
}
|
||||
DEBUG(printf("Num: %d\n", num));
|
||||
|
||||
stack[depth++] = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_add()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] + stack[depth];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_sub()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] - stack[depth];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan(char *s, int l)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = 0;
|
||||
char *t;
|
||||
int res = 0;
|
||||
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT (s+l+1)
|
||||
#define YYMARKER q
|
||||
#define YYFILL(n) { return depth == 1 ? 0 : 2; }
|
||||
|
||||
while(!res)
|
||||
{
|
||||
t = p;
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
|
||||
DIGIT = [0-9] ;
|
||||
OCT = "0" DIGIT+ ;
|
||||
INT = "0" | ( [1-9] DIGIT* ) ;
|
||||
WS = [ \t]+ ;
|
||||
|
||||
WS { continue; }
|
||||
OCT { res = push_num(t, p, 8); continue; }
|
||||
INT { res = push_num(t, p, 10); continue; }
|
||||
"+" { res = stack_add(); continue; }
|
||||
"-" { res = stack_sub(); continue; }
|
||||
[^] { res = 1; continue; }
|
||||
*/
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
char *inp;
|
||||
int res = 0, argp = 0, len;
|
||||
|
||||
while(!res && ++argp < argc)
|
||||
{
|
||||
inp = argv[argp];
|
||||
len = strlen(inp);
|
||||
if (inp[0] == '\"' && inp[len-1] == '\"')
|
||||
{
|
||||
++inp;
|
||||
len -=2;
|
||||
}
|
||||
res = scan(inp, len);
|
||||
}
|
||||
switch(res)
|
||||
{
|
||||
case 0:
|
||||
printf("Result: %d\n", stack[0]);
|
||||
return 0;
|
||||
case 1:
|
||||
fprintf(stderr, "Illegal character in input.\n");
|
||||
return 1;
|
||||
case 2:
|
||||
fprintf(stderr, "Premature end of input.\n");
|
||||
return 2;
|
||||
case 3:
|
||||
fprintf(stderr, "Stack overflow.\n");
|
||||
return 3;
|
||||
case 4:
|
||||
fprintf(stderr, "Stack underflow.\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "calc_006.s.re"
|
||||
/* re2c lesson 001_upn_calculator, calc_006, (c) M. Boerger 2006 - 2007 */
|
||||
#line 36 "calc_006.s.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG(stmt) stmt
|
||||
|
||||
int stack[4];
|
||||
int depth = 0;
|
||||
|
||||
int push_num(const unsigned char *t, const unsigned char *l, int radix)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (depth >= sizeof(stack))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
--t;
|
||||
while(++t < l)
|
||||
{
|
||||
num = num * radix + (*t - (unsigned char)'0');
|
||||
}
|
||||
DEBUG(printf("Num: %d\n", num));
|
||||
|
||||
stack[depth++] = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_add()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] + stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_sub()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] - stack[depth];
|
||||
DEBUG(printf("-\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan(char *s)
|
||||
{
|
||||
unsigned char *p = (unsigned char*)s;
|
||||
unsigned char *t;
|
||||
int res = 0;
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR p
|
||||
|
||||
while(!res)
|
||||
{
|
||||
t = p;
|
||||
|
||||
#line 69 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= '*') {
|
||||
if (yych <= '\t') {
|
||||
if (yych <= 0x00) goto yy11;
|
||||
if (yych <= 0x08) goto yy13;
|
||||
} else {
|
||||
if (yych != ' ') goto yy13;
|
||||
}
|
||||
} else {
|
||||
if (yych <= '-') {
|
||||
if (yych <= '+') goto yy7;
|
||||
if (yych <= ',') goto yy13;
|
||||
goto yy9;
|
||||
} else {
|
||||
if (yych <= '/') goto yy13;
|
||||
if (yych <= '0') goto yy4;
|
||||
if (yych <= '9') goto yy6;
|
||||
goto yy13;
|
||||
}
|
||||
}
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy21;
|
||||
yy3:
|
||||
#line 107 "calc_006.s.re"
|
||||
{ continue; }
|
||||
#line 99 "<stdout>"
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) <= '/') goto yy5;
|
||||
if (yych <= '9') goto yy17;
|
||||
yy5:
|
||||
#line 109 "calc_006.s.re"
|
||||
{ res = push_num(t, p, 10); continue; }
|
||||
#line 107 "<stdout>"
|
||||
yy6:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy16;
|
||||
yy7:
|
||||
++YYCURSOR;
|
||||
#line 110 "calc_006.s.re"
|
||||
{ res = stack_add(); continue; }
|
||||
#line 115 "<stdout>"
|
||||
yy9:
|
||||
++YYCURSOR;
|
||||
#line 111 "calc_006.s.re"
|
||||
{ res = stack_sub(); continue; }
|
||||
#line 120 "<stdout>"
|
||||
yy11:
|
||||
++YYCURSOR;
|
||||
#line 112 "calc_006.s.re"
|
||||
{ res = depth == 1 ? 0 : 2; break; }
|
||||
#line 125 "<stdout>"
|
||||
yy13:
|
||||
++YYCURSOR;
|
||||
#line 113 "calc_006.s.re"
|
||||
{ res = 1; continue; }
|
||||
#line 130 "<stdout>"
|
||||
yy15:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
yy16:
|
||||
if (yych <= '/') goto yy5;
|
||||
if (yych <= '9') goto yy15;
|
||||
goto yy5;
|
||||
yy17:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= '/') goto yy19;
|
||||
if (yych <= '9') goto yy17;
|
||||
yy19:
|
||||
#line 108 "calc_006.s.re"
|
||||
{ res = push_num(t, p, 8); continue; }
|
||||
#line 146 "<stdout>"
|
||||
yy20:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
yy21:
|
||||
if (yych == '\t') goto yy20;
|
||||
if (yych == ' ') goto yy20;
|
||||
goto yy3;
|
||||
}
|
||||
#line 114 "calc_006.s.re"
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
char *inp;
|
||||
int res = 0, argp = 0, len;
|
||||
|
||||
while(!res && ++argp < argc)
|
||||
{
|
||||
inp = strdup(argv[argp]);
|
||||
len = strlen(inp);
|
||||
if (inp[0] == '\"' && inp[len-1] == '\"')
|
||||
{
|
||||
inp[len - 1] = '\0';
|
||||
++inp;
|
||||
}
|
||||
res = scan(inp);
|
||||
free(inp);
|
||||
}
|
||||
switch(res)
|
||||
{
|
||||
case 0:
|
||||
printf("Result: %d\n", stack[0]);
|
||||
return 0;
|
||||
case 1:
|
||||
fprintf(stderr, "Illegal character in input.\n");
|
||||
return 1;
|
||||
case 2:
|
||||
fprintf(stderr, "Premature end of input.\n");
|
||||
return 2;
|
||||
case 3:
|
||||
fprintf(stderr, "Stack overflow.\n");
|
||||
return 3;
|
||||
case 4:
|
||||
fprintf(stderr, "Stack underflow.\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, calc_006, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- avoiding YYFILL()
|
||||
. We use the inplace configuration re2c:yyfill to suppress generation of
|
||||
YYFILL() blocks. This of course means we no longer have to provide the
|
||||
macro.
|
||||
. We also drop the YYMARKER stuff since we know that re2c does not generate
|
||||
it for this example.
|
||||
. Since re2c does no longer check for out of data situations we must do this.
|
||||
For that reason we first reintroduce our zero rule and second we need to
|
||||
ensure that the scanner does not take more than one bytes in one go.
|
||||
|
||||
In the example suppose "0" is passed. The scanner reads the first "0" and
|
||||
then is in an undecided state. The scanner can earliest decide on the next
|
||||
char what the token is. In case of a zero the input ends and it was a
|
||||
number, 0 to be precise. In case of a digit it is an octal number and the
|
||||
next character needs to be read. In case of any other character the scanner
|
||||
will detect an error with the any rule [^].
|
||||
|
||||
Now the above shows that the scanner may read two characters directly. But
|
||||
only if the first is a "0". So we could easily check that if the first char
|
||||
is "0" and the next char is a digit then yet another charcter is present.
|
||||
But we require our inut to be zero terminated. And that means we do not
|
||||
have to check anything for this scanner.
|
||||
|
||||
However with other rule sets re2c might read more then one character in a
|
||||
row. In those cases it is normally hard to impossible to avoid YYFILL.
|
||||
|
||||
- optimizing the generated code by using -s command line switch of re2c
|
||||
. This tells re2c to generate code that uses if statements rather
|
||||
then endless switch/case expressions where appropriate. Note that the
|
||||
generated code now requires the input to be unsigned char rather than char
|
||||
due to the way comparisons are generated.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG(stmt) stmt
|
||||
|
||||
int stack[4];
|
||||
int depth = 0;
|
||||
|
||||
int push_num(const unsigned char *t, const unsigned char *l, int radix)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (depth >= sizeof(stack))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
--t;
|
||||
while(++t < l)
|
||||
{
|
||||
num = num * radix + (*t - (unsigned char)'0');
|
||||
}
|
||||
DEBUG(printf("Num: %d\n", num));
|
||||
|
||||
stack[depth++] = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_add()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] + stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_sub()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] - stack[depth];
|
||||
DEBUG(printf("-\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan(char *s)
|
||||
{
|
||||
unsigned char *p = (unsigned char*)s;
|
||||
unsigned char *t;
|
||||
int res = 0;
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR p
|
||||
|
||||
while(!res)
|
||||
{
|
||||
t = p;
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
re2c:yyfill:enable = 0;
|
||||
|
||||
DIGIT = [0-9] ;
|
||||
OCT = "0" DIGIT+ ;
|
||||
INT = "0" | ( [1-9] DIGIT* ) ;
|
||||
WS = [ \t]+ ;
|
||||
|
||||
WS { continue; }
|
||||
OCT { res = push_num(t, p, 8); continue; }
|
||||
INT { res = push_num(t, p, 10); continue; }
|
||||
"+" { res = stack_add(); continue; }
|
||||
"-" { res = stack_sub(); continue; }
|
||||
"\000" { res = depth == 1 ? 0 : 2; break; }
|
||||
[^] { res = 1; continue; }
|
||||
*/
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
char *inp;
|
||||
int res = 0, argp = 0, len;
|
||||
|
||||
while(!res && ++argp < argc)
|
||||
{
|
||||
inp = strdup(argv[argp]);
|
||||
len = strlen(inp);
|
||||
if (inp[0] == '\"' && inp[len-1] == '\"')
|
||||
{
|
||||
inp[len - 1] = '\0';
|
||||
++inp;
|
||||
}
|
||||
res = scan(inp);
|
||||
free(inp);
|
||||
}
|
||||
switch(res)
|
||||
{
|
||||
case 0:
|
||||
printf("Result: %d\n", stack[0]);
|
||||
return 0;
|
||||
case 1:
|
||||
fprintf(stderr, "Illegal character in input.\n");
|
||||
return 1;
|
||||
case 2:
|
||||
fprintf(stderr, "Premature end of input.\n");
|
||||
return 2;
|
||||
case 3:
|
||||
fprintf(stderr, "Stack overflow.\n");
|
||||
return 3;
|
||||
case 4:
|
||||
fprintf(stderr, "Stack underflow.\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "calc_007.b.re"
|
||||
/* re2c lesson 001_upn_calculator, calc_007, (c) M. Boerger 2006 - 2007 */
|
||||
#line 9 "calc_007.b.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG(stmt) stmt
|
||||
|
||||
int stack[4];
|
||||
int depth = 0;
|
||||
|
||||
int push_num(const unsigned char *t, const unsigned char *l, int radix)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (depth >= sizeof(stack))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
--t;
|
||||
while(++t < l)
|
||||
{
|
||||
num = num * radix + (*t - (unsigned char)'0');
|
||||
}
|
||||
DEBUG(printf("Num: %d\n", num));
|
||||
|
||||
stack[depth++] = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_add()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] + stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_sub()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] - stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan(char *s)
|
||||
{
|
||||
unsigned char *p = (unsigned char*)s;
|
||||
unsigned char *t;
|
||||
int res = 0;
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR p
|
||||
|
||||
while(!res)
|
||||
{
|
||||
t = p;
|
||||
|
||||
#line 69 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
static const unsigned char yybm[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 128, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
128, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= '*') {
|
||||
if (yych <= '\t') {
|
||||
if (yych <= 0x00) goto yy11;
|
||||
if (yych <= 0x08) goto yy13;
|
||||
} else {
|
||||
if (yych != ' ') goto yy13;
|
||||
}
|
||||
} else {
|
||||
if (yych <= '-') {
|
||||
if (yych <= '+') goto yy7;
|
||||
if (yych <= ',') goto yy13;
|
||||
goto yy9;
|
||||
} else {
|
||||
if (yych <= '/') goto yy13;
|
||||
if (yych <= '0') goto yy4;
|
||||
if (yych <= '9') goto yy6;
|
||||
goto yy13;
|
||||
}
|
||||
}
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy21;
|
||||
yy3:
|
||||
#line 80 "calc_007.b.re"
|
||||
{ continue; }
|
||||
#line 133 "<stdout>"
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) <= '/') goto yy5;
|
||||
if (yych <= '9') goto yy17;
|
||||
yy5:
|
||||
#line 82 "calc_007.b.re"
|
||||
{ res = push_num(t, p, 10); continue; }
|
||||
#line 141 "<stdout>"
|
||||
yy6:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy16;
|
||||
yy7:
|
||||
++YYCURSOR;
|
||||
#line 83 "calc_007.b.re"
|
||||
{ res = stack_add(); continue; }
|
||||
#line 149 "<stdout>"
|
||||
yy9:
|
||||
++YYCURSOR;
|
||||
#line 84 "calc_007.b.re"
|
||||
{ res = stack_sub(); continue; }
|
||||
#line 154 "<stdout>"
|
||||
yy11:
|
||||
++YYCURSOR;
|
||||
#line 85 "calc_007.b.re"
|
||||
{ res = depth == 1 ? 0 : 2; break; }
|
||||
#line 159 "<stdout>"
|
||||
yy13:
|
||||
++YYCURSOR;
|
||||
#line 86 "calc_007.b.re"
|
||||
{ res = 1; continue; }
|
||||
#line 164 "<stdout>"
|
||||
yy15:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
yy16:
|
||||
if (yybm[0+yych] & 64) {
|
||||
goto yy15;
|
||||
}
|
||||
goto yy5;
|
||||
yy17:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= '/') goto yy19;
|
||||
if (yych <= '9') goto yy17;
|
||||
yy19:
|
||||
#line 81 "calc_007.b.re"
|
||||
{ res = push_num(t, p, 8); continue; }
|
||||
#line 181 "<stdout>"
|
||||
yy20:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
yy21:
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy20;
|
||||
}
|
||||
goto yy3;
|
||||
}
|
||||
#line 87 "calc_007.b.re"
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
char *inp;
|
||||
int res = 0, argp = 0, len;
|
||||
|
||||
while(!res && ++argp < argc)
|
||||
{
|
||||
inp = strdup(argv[argp]);
|
||||
len = strlen(inp);
|
||||
if (inp[0] == '\"' && inp[len-1] == '\"')
|
||||
{
|
||||
inp[len - 1] = '\0';
|
||||
++inp;
|
||||
}
|
||||
res = scan(inp);
|
||||
free(inp);
|
||||
}
|
||||
switch(res)
|
||||
{
|
||||
case 0:
|
||||
printf("Result: %d\n", stack[0]);
|
||||
return 0;
|
||||
case 1:
|
||||
fprintf(stderr, "Illegal character in input.\n");
|
||||
return 1;
|
||||
case 2:
|
||||
fprintf(stderr, "Premature end of input.\n");
|
||||
return 2;
|
||||
case 3:
|
||||
fprintf(stderr, "Stack overflow.\n");
|
||||
return 3;
|
||||
case 4:
|
||||
fprintf(stderr, "Stack underflow.\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, calc_007, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- optimizing the generated code by using -b command line switch of re2c
|
||||
. This tells re2c to generate code that uses a decision table. The -b switch
|
||||
also contains the -s behavior. And -b also requires the input to be
|
||||
unsigned chars.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG(stmt) stmt
|
||||
|
||||
int stack[4];
|
||||
int depth = 0;
|
||||
|
||||
int push_num(const unsigned char *t, const unsigned char *l, int radix)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (depth >= sizeof(stack))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
--t;
|
||||
while(++t < l)
|
||||
{
|
||||
num = num * radix + (*t - (unsigned char)'0');
|
||||
}
|
||||
DEBUG(printf("Num: %d\n", num));
|
||||
|
||||
stack[depth++] = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_add()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] + stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_sub()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] - stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan(char *s)
|
||||
{
|
||||
unsigned char *p = (unsigned char*)s;
|
||||
unsigned char *t;
|
||||
int res = 0;
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR p
|
||||
|
||||
while(!res)
|
||||
{
|
||||
t = p;
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
re2c:yyfill:enable = 0;
|
||||
|
||||
DIGIT = [0-9] ;
|
||||
OCT = "0" DIGIT+ ;
|
||||
INT = "0" | ( [1-9] DIGIT* ) ;
|
||||
WS = [ \t]+ ;
|
||||
|
||||
WS { continue; }
|
||||
OCT { res = push_num(t, p, 8); continue; }
|
||||
INT { res = push_num(t, p, 10); continue; }
|
||||
"+" { res = stack_add(); continue; }
|
||||
"-" { res = stack_sub(); continue; }
|
||||
"\000" { res = depth == 1 ? 0 : 2; break; }
|
||||
[^] { res = 1; continue; }
|
||||
*/
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
char *inp;
|
||||
int res = 0, argp = 0, len;
|
||||
|
||||
while(!res && ++argp < argc)
|
||||
{
|
||||
inp = strdup(argv[argp]);
|
||||
len = strlen(inp);
|
||||
if (inp[0] == '\"' && inp[len-1] == '\"')
|
||||
{
|
||||
inp[len - 1] = '\0';
|
||||
++inp;
|
||||
}
|
||||
res = scan(inp);
|
||||
free(inp);
|
||||
}
|
||||
switch(res)
|
||||
{
|
||||
case 0:
|
||||
printf("Result: %d\n", stack[0]);
|
||||
return 0;
|
||||
case 1:
|
||||
fprintf(stderr, "Illegal character in input.\n");
|
||||
return 1;
|
||||
case 2:
|
||||
fprintf(stderr, "Premature end of input.\n");
|
||||
return 2;
|
||||
case 3:
|
||||
fprintf(stderr, "Stack overflow.\n");
|
||||
return 3;
|
||||
case 4:
|
||||
fprintf(stderr, "Stack underflow.\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "calc_008.b.re"
|
||||
/* re2c lesson 001_upn_calculator, calc_008, (c) M. Boerger 2006 - 2007 */
|
||||
#line 31 "calc_008.b.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG(stmt) stmt
|
||||
|
||||
int stack[4];
|
||||
int depth = 0;
|
||||
|
||||
int push_num(const char *t, const char *l, int radix)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (depth >= sizeof(stack))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
--t;
|
||||
while(++t < l)
|
||||
{
|
||||
num = num * radix + (*t - '0');
|
||||
}
|
||||
DEBUG(printf("Num: %d\n", num));
|
||||
|
||||
stack[depth++] = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_add()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] + stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_sub()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] - stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan(char *p)
|
||||
{
|
||||
char *t;
|
||||
int res = 0;
|
||||
|
||||
while(!res)
|
||||
{
|
||||
t = p;
|
||||
|
||||
#line 65 "<stdout>"
|
||||
{
|
||||
unsigned char curr;
|
||||
static const unsigned char yybm[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 128, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
128, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
curr = (unsigned char)*p;
|
||||
if (curr <= '*') {
|
||||
if (curr <= '\t') {
|
||||
if (curr <= 0x00) goto scan11;
|
||||
if (curr <= 0x08) goto scan13;
|
||||
} else {
|
||||
if (curr != ' ') goto scan13;
|
||||
}
|
||||
} else {
|
||||
if (curr <= '-') {
|
||||
if (curr <= '+') goto scan7;
|
||||
if (curr <= ',') goto scan13;
|
||||
goto scan9;
|
||||
} else {
|
||||
if (curr <= '/') goto scan13;
|
||||
if (curr <= '0') goto scan4;
|
||||
if (curr <= '9') goto scan6;
|
||||
goto scan13;
|
||||
}
|
||||
}
|
||||
++p;
|
||||
curr = (unsigned char)*p;
|
||||
goto scan21;
|
||||
scan3:
|
||||
#line 103 "calc_008.b.re"
|
||||
{ continue; }
|
||||
#line 129 "<stdout>"
|
||||
scan4:
|
||||
++p;
|
||||
if ((curr = (unsigned char)*p) <= '/') goto scan5;
|
||||
if (curr <= '9') goto scan17;
|
||||
scan5:
|
||||
#line 105 "calc_008.b.re"
|
||||
{ res = push_num(t, p, 10); continue; }
|
||||
#line 137 "<stdout>"
|
||||
scan6:
|
||||
curr = (unsigned char)*++p;
|
||||
goto scan16;
|
||||
scan7:
|
||||
++p;
|
||||
#line 106 "calc_008.b.re"
|
||||
{ res = stack_add(); continue; }
|
||||
#line 145 "<stdout>"
|
||||
scan9:
|
||||
++p;
|
||||
#line 107 "calc_008.b.re"
|
||||
{ res = stack_sub(); continue; }
|
||||
#line 150 "<stdout>"
|
||||
scan11:
|
||||
++p;
|
||||
#line 108 "calc_008.b.re"
|
||||
{ res = depth == 1 ? 0 : 2; break; }
|
||||
#line 155 "<stdout>"
|
||||
scan13:
|
||||
++p;
|
||||
#line 109 "calc_008.b.re"
|
||||
{ res = 1; continue; }
|
||||
#line 160 "<stdout>"
|
||||
scan15:
|
||||
++p;
|
||||
curr = (unsigned char)*p;
|
||||
scan16:
|
||||
if (yybm[0+curr] & 64) {
|
||||
goto scan15;
|
||||
}
|
||||
goto scan5;
|
||||
scan17:
|
||||
++p;
|
||||
curr = (unsigned char)*p;
|
||||
if (curr <= '/') goto scan19;
|
||||
if (curr <= '9') goto scan17;
|
||||
scan19:
|
||||
#line 104 "calc_008.b.re"
|
||||
{ res = push_num(t, p, 8); continue; }
|
||||
#line 177 "<stdout>"
|
||||
scan20:
|
||||
++p;
|
||||
curr = (unsigned char)*p;
|
||||
scan21:
|
||||
if (yybm[0+curr] & 128) {
|
||||
goto scan20;
|
||||
}
|
||||
goto scan3;
|
||||
}
|
||||
#line 110 "calc_008.b.re"
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
char *inp;
|
||||
int res = 0, argp = 0, len;
|
||||
|
||||
while(!res && ++argp < argc)
|
||||
{
|
||||
inp = strdup(argv[argp]);
|
||||
len = strlen(inp);
|
||||
if (inp[0] == '\"' && inp[len-1] == '\"')
|
||||
{
|
||||
inp[len - 1] = '\0';
|
||||
++inp;
|
||||
}
|
||||
res = scan(inp);
|
||||
free(inp);
|
||||
}
|
||||
switch(res)
|
||||
{
|
||||
case 0:
|
||||
printf("Result: %d\n", stack[0]);
|
||||
return 0;
|
||||
case 1:
|
||||
fprintf(stderr, "Illegal character in input.\n");
|
||||
return 1;
|
||||
case 2:
|
||||
fprintf(stderr, "Premature end of input.\n");
|
||||
return 2;
|
||||
case 3:
|
||||
fprintf(stderr, "Stack overflow.\n");
|
||||
return 3;
|
||||
case 4:
|
||||
fprintf(stderr, "Stack underflow.\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, calc_008, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- using -b with signed character input
|
||||
. Since the code is being generated with -b switch re2c requires the internal
|
||||
character variable yych to use an unsigned character type. For that reason
|
||||
the previous lessons had a conversion at the beginning of their scan()
|
||||
function. Other re2c generated code often have the scanners work completely
|
||||
on unsigned input. Thus requesting a conversion.
|
||||
|
||||
To avoid the conversion on input, re2c allows to do the conversion when
|
||||
reading the internal yych variable. To enable that conversion you need to
|
||||
use the implace configuration 're2c:yych:conversion' and set it to 1. This
|
||||
will change the generated code to insert conversions to YYCTYPE whenever
|
||||
yych is being read.
|
||||
|
||||
- More inplace configurations for better/nicer code
|
||||
. re2c allows to overwrite the generation of any define, label or variable
|
||||
used in the generated code. For example we overwrite the 'yych' variable
|
||||
name to 'curr' using inplace configuration 're2c:variable:yych = curr;'.
|
||||
|
||||
. We further more use inplace configurations instead of defines. This allows
|
||||
to use correct conversions to 'unsigned char' instead of having to convert
|
||||
to 'YYCTYPE' when placing 're2c:define:YYCTYPE = "unsigned char";' infront
|
||||
of 're2c:yych:conversion'. Note that we have to use apostrophies for the
|
||||
first setting as it contains a space.
|
||||
|
||||
. Last but not least we use 're2c:labelprefix = scan' to change the prefix
|
||||
of generated labels.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG(stmt) stmt
|
||||
|
||||
int stack[4];
|
||||
int depth = 0;
|
||||
|
||||
int push_num(const char *t, const char *l, int radix)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (depth >= sizeof(stack))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
--t;
|
||||
while(++t < l)
|
||||
{
|
||||
num = num * radix + (*t - '0');
|
||||
}
|
||||
DEBUG(printf("Num: %d\n", num));
|
||||
|
||||
stack[depth++] = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_add()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] + stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stack_sub()
|
||||
{
|
||||
if (depth < 2) return 4;
|
||||
|
||||
--depth;
|
||||
stack[depth-1] = stack[depth-1] - stack[depth];
|
||||
DEBUG(printf("+\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan(char *p)
|
||||
{
|
||||
char *t;
|
||||
int res = 0;
|
||||
|
||||
while(!res)
|
||||
{
|
||||
t = p;
|
||||
/*!re2c
|
||||
re2c:define:YYCTYPE = "unsigned char";
|
||||
re2c:define:YYCURSOR = p;
|
||||
re2c:variable:yych = curr;
|
||||
re2c:indent:top = 2;
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:yych:conversion = 1;
|
||||
re2c:labelprefix = scan;
|
||||
|
||||
DIGIT = [0-9] ;
|
||||
OCT = "0" DIGIT+ ;
|
||||
INT = "0" | ( [1-9] DIGIT* ) ;
|
||||
WS = [ \t]+ ;
|
||||
|
||||
WS { continue; }
|
||||
OCT { res = push_num(t, p, 8); continue; }
|
||||
INT { res = push_num(t, p, 10); continue; }
|
||||
"+" { res = stack_add(); continue; }
|
||||
"-" { res = stack_sub(); continue; }
|
||||
"\000" { res = depth == 1 ? 0 : 2; break; }
|
||||
[^] { res = 1; continue; }
|
||||
*/
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
char *inp;
|
||||
int res = 0, argp = 0, len;
|
||||
|
||||
while(!res && ++argp < argc)
|
||||
{
|
||||
inp = strdup(argv[argp]);
|
||||
len = strlen(inp);
|
||||
if (inp[0] == '\"' && inp[len-1] == '\"')
|
||||
{
|
||||
inp[len - 1] = '\0';
|
||||
++inp;
|
||||
}
|
||||
res = scan(inp);
|
||||
free(inp);
|
||||
}
|
||||
switch(res)
|
||||
{
|
||||
case 0:
|
||||
printf("Result: %d\n", stack[0]);
|
||||
return 0;
|
||||
case 1:
|
||||
fprintf(stderr, "Illegal character in input.\n");
|
||||
return 1;
|
||||
case 2:
|
||||
fprintf(stderr, "Premature end of input.\n");
|
||||
return 2;
|
||||
case 3:
|
||||
fprintf(stderr, "Stack overflow.\n");
|
||||
return 3;
|
||||
case 4:
|
||||
fprintf(stderr, "Stack underflow.\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
re2c lesson 001_upn_calculator, (c) M. Boerger 2006
|
||||
|
||||
This lesson gets you started with re2c. In the end you will have an easy RPN
|
||||
(reverse polish notation) calculator for use at command line.
|
||||
|
||||
You will learn about the basic interface of re2c when scanning input strings.
|
||||
How to detect the end of the input and use that to stop scanning in order to
|
||||
avoid problems.
|
||||
|
||||
Once you have successfully installed re2c you can use it to generate *.c files
|
||||
from the *.re files presented in this lesson. Actually the expected *.c files
|
||||
are already present. So you should name them *.cc or something alike or just
|
||||
give them a different name like test.c. To do so you simply change into the
|
||||
directory and execute the following command:
|
||||
|
||||
re2c calc_001.re > test.c
|
||||
|
||||
Then use your compiler to compile that code and run it. If you are using gcc
|
||||
you simply do the following:
|
||||
|
||||
gcc -o test.o test.c
|
||||
./test.o <input_file_name>
|
||||
|
||||
If you are using windows you might want to read till the end of this lesson.
|
||||
|
||||
When you want to debug the code it helps to make re2c generate working #line
|
||||
information. To do so you simply specify the output file using the -o switch
|
||||
followed by the output filename:
|
||||
|
||||
re2c -o test.c calc_001.re
|
||||
|
||||
The input files *.re each contain basic step by comments that explain what is
|
||||
going on and what you can see in the examples.
|
||||
|
||||
In order to optimize the generated code we will use the -s command line switch
|
||||
of re2c. This tells re2c to generate code that uses if statements rather
|
||||
then endless switch/case expressions where appropriate. Note that the file name
|
||||
extension is actually '.s.re' to tell the test system to use the -s switch. To
|
||||
invoke re2 you do the following:
|
||||
|
||||
re2c -s -o test.c calc_006.s.re
|
||||
|
||||
Finally we use the -b switch to have the code use a decision table. The -b
|
||||
switch also contains the -s behavior.
|
||||
|
||||
re2c -b -o test.c calc_007.b.re
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
For windows users Lynn Allan provided some additional stuff to get you started
|
||||
in the Microsoft world. This addon resides in the windows subdirectory and
|
||||
gives you something to expereiment with. The code in that directory is based
|
||||
on the first step and has the following changes:
|
||||
|
||||
* vc6 .dsp/.dsw and vc7/vc8 .sln/.vcproj project files that have "Custom Build
|
||||
Steps" that can tell when main.re changes, and know how to generate main.c
|
||||
from main.re. They assume that you unpacked the zip package and have re2c
|
||||
itself build or installed in Release and Release-2005 directory respectively.
|
||||
If re2c cannot be found you need to modify the custom build step and correct
|
||||
the path to re2c.
|
||||
|
||||
* BuildAndRun.bat to do command line rec2 and then cl and then run the
|
||||
executable (discontinues with message if errors).
|
||||
|
||||
* built-in cppunit-like test to confirm it worked as expected.
|
||||
|
||||
* array of test strings "fed" to scan rather than file contents to facilitate
|
||||
testing and also reduce the newbie learning curve.
|
||||
|
||||
* HiResTimer output for 10,000 loops and 100,000 loops. While this might be
|
||||
excessive for this lesson, it illustrates how to do it for subsequent lessons
|
||||
and your own stuff using windows. Also it shows that Release build is as fast
|
||||
as strncmp for this test and can probably be made significantly faster.
|
||||
|
||||
* If you want to build the other steps of this lesson using windows tools
|
||||
simply copy the *.re files into the windows directory as main.re and rebuild.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Sidenote: UPN is the german translation of RPN, somehow hardcoded into the
|
||||
authors brain :-)
|
||||
@@ -1,48 +0,0 @@
|
||||
@echo OFF
|
||||
goto Start
|
||||
rem BuildAndRun.bat 06-Apr-15 lda
|
||||
rem Assumes re2c.exe findable with PATH or . or .. or ..\.. or $(RE2C_HOME)
|
||||
rem Assumes cl.exe findable with PATH or VcToolKit2003 installed
|
||||
|
||||
:Start
|
||||
if exist %RE2C_HOME%\re2c.exe goto ProceedWithGenerate
|
||||
if exist .\re2c.exe set RE2C_HOME=.
|
||||
if exist ..\re2c.exe set RE2C_HOME=..
|
||||
if exist ..\..\re2c.exe set RE2C_HOME=..\..
|
||||
if exist ..\..\..\re2c.exe set RE2C_HOME=..\..\..
|
||||
if exist ..\..\..\Release\re2c.exe set RE2C_HOME=..\..\..\Release
|
||||
if exist ..\..\..\Release-2005\re2c.exe set RE2C_HOME=..\..\..\Release-2005
|
||||
if not exist %RE2C_HOME%\re2c.exe goto ReportSetupError
|
||||
|
||||
:ProceedWithGenerate
|
||||
set BASE_FILE_NAME=main
|
||||
%RE2C_HOME%\re2c -b -o%BASE_FILE_NAME%.c %BASE_FILE_NAME%.re
|
||||
rem echo ErrorLevel is set to %ERRORLEVEL% after re2c
|
||||
IF ERRORLEVEL 1 goto ReportRe2cError
|
||||
|
||||
rem (to test) set path=
|
||||
cl 1>nul 2>nul
|
||||
IF ERRORLEVEL 1 goto AttemptToSetupCompiler
|
||||
goto ProceedWithCompile
|
||||
|
||||
:AttemptToSetupCompiler
|
||||
echo ErrorLevel is set to %ERRORLEVEL% after blank cl command line
|
||||
call %VCToolkitInstallDir%\vcvars32.bat 1>nul 2>nul
|
||||
cl 1>nul 2>nul
|
||||
IF ERRORLEVEL 1 goto ReportClError
|
||||
|
||||
:ProceedWithCompile
|
||||
cl -O2 /DNDEBUG /D_CONSOLE /DWIN32 %BASE_FILE_NAME%.c
|
||||
rem echo ErrorLevel is set to %ERRORLEVEL% after cl
|
||||
IF ERRORLEVEL 1 goto ReportClError
|
||||
%BASE_FILE_NAME%
|
||||
goto AllDone
|
||||
|
||||
:ReportSetupError
|
||||
echo re2c.exe not found in ., .., ..\.., ..\..\.., ..\..\..\Release
|
||||
echo or ..\..\..\Release-2005 Environment variable RE2C_HOME invalid or not set?
|
||||
|
||||
:ReportClError
|
||||
:ReportRe2cError
|
||||
:AllDone
|
||||
pause
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* @file HiResTimer.h
|
||||
* @brief
|
||||
* @note
|
||||
*/
|
||||
|
||||
#ifndef _HI_RES_TIMER_H_
|
||||
#define _HI_RES_TIMER_H_
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h> // probably already done in stdafx.h
|
||||
static LARGE_INTEGER start;
|
||||
static LARGE_INTEGER stop;
|
||||
static LARGE_INTEGER freq;
|
||||
static _int64 elapsedCounts;
|
||||
static double elapsedMillis;
|
||||
static double elapsedMicros;
|
||||
static HANDLE processHandle;
|
||||
static DWORD prevPriorityClass;
|
||||
|
||||
void HrtInit()
|
||||
{
|
||||
processHandle = GetCurrentProcess();
|
||||
prevPriorityClass = GetPriorityClass(processHandle);
|
||||
QueryPerformanceFrequency(&freq);
|
||||
}
|
||||
|
||||
void HrtStart()
|
||||
{
|
||||
QueryPerformanceCounter(&start);
|
||||
}
|
||||
|
||||
void HrtSetPriority(DWORD priority)
|
||||
{
|
||||
int flag;
|
||||
prevPriorityClass = GetPriorityClass(processHandle);
|
||||
flag = SetPriorityClass(processHandle, priority);
|
||||
}
|
||||
|
||||
void HrtResetPriority(void)
|
||||
{
|
||||
int flag = SetPriorityClass(processHandle, prevPriorityClass);
|
||||
}
|
||||
|
||||
double HrtElapsedMillis()
|
||||
{
|
||||
QueryPerformanceCounter(&stop);
|
||||
elapsedCounts = (stop.QuadPart - start.QuadPart);
|
||||
elapsedMillis = ((elapsedCounts * 1000.0) / freq.QuadPart);
|
||||
return elapsedMillis;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRe2c", "TestRe2c-2005.vcproj", "{E2CEB3D0-066A-4C9A-B32C-B2197448A57A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Default = Debug|Default
|
||||
Release|Default = Release|Default
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E2CEB3D0-066A-4C9A-B32C-B2197448A57A}.Debug|Default.ActiveCfg = Debug|Win32
|
||||
{E2CEB3D0-066A-4C9A-B32C-B2197448A57A}.Debug|Default.Build.0 = Debug|Win32
|
||||
{E2CEB3D0-066A-4C9A-B32C-B2197448A57A}.Release|Default.ActiveCfg = Release|Win32
|
||||
{E2CEB3D0-066A-4C9A-B32C-B2197448A57A}.Release|Default.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,252 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="TestRe2c"
|
||||
ProjectGUID="{E2CEB3D0-066A-4C9A-B32C-B2197448A57A}"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\Debug/TestRe2c.tlb"
|
||||
HeaderFileName=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderThrough=""
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile=".\Debug/TestRe2c.exe"
|
||||
LinkIncremental="0"
|
||||
SuppressStartupBanner="true"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile=".\Debug/TestRe2c.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\Release/TestRe2c.tlb"
|
||||
HeaderFileName=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/O2"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderThrough=""
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile=".\Release/TestRe2c.exe"
|
||||
LinkIncremental="0"
|
||||
SuppressStartupBanner="true"
|
||||
ProgramDatabaseFile=".\Release/TestRe2c.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
>
|
||||
<File
|
||||
RelativePath="main.b.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="main.b.re"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Generate $(InputName).c from $(InputName).re using Re2c"
|
||||
CommandLine="..\..\..\Release-2005\re2c.exe -b -o$(InputName).c $(InputName).re
"
|
||||
Outputs="$(InputName).c"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Generate $(InputName).c from $(InputName).re using Re2c"
|
||||
CommandLine="..\..\..\Rlease-2005\re2c.exe -b -o$(InputName).c $(InputName).re
"
|
||||
Outputs="$(InputName).c"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,124 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="TestRe2c" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** NICHT BEARBEITEN **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=TestRe2c - Win32 Debug
|
||||
!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
|
||||
!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "TestRe2c.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
|
||||
!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "TestRe2c.mak" CFG="TestRe2c - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Für die Konfiguration stehen zur Auswahl:
|
||||
!MESSAGE
|
||||
!MESSAGE "TestRe2c - Win32 Release" (basierend auf "Win32 (x86) Console Application")
|
||||
!MESSAGE "TestRe2c - Win32 Debug" (basierend auf "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=xicl6.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "TestRe2c - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=xilink6.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "TestRe2c - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=xilink6.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "TestRe2c - Win32 Release"
|
||||
# Name "TestRe2c - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\main.b.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\main.b.re
|
||||
|
||||
!IF "$(CFG)" == "TestRe2c - Win32 Release"
|
||||
|
||||
# Begin Custom Build - Generate $(InputName).c from $(InputName).re using Re2c
|
||||
InputPath=.\main.b.re
|
||||
InputName=main.b
|
||||
|
||||
"$(InputName).c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
..\..\..\Release-2005\re2c -b -o$(InputName).c $(InputName).re
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ELSEIF "$(CFG)" == "TestRe2c - Win32 Debug"
|
||||
|
||||
# Begin Custom Build - Generate $(InputName).c from $(InputName).re using Re2c
|
||||
InputPath=.\main.b.re
|
||||
InputName=main.b
|
||||
|
||||
"$(InputName).c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
..\..\..\Release-2005\re2c -b -o$(InputName).c $(InputName).re
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,29 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "TestRe2c"=.\TestRe2c.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Binary file not shown.
@@ -1,21 +0,0 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRe2c", "TestRe2c.vcproj", "{BEC086F1-62CD-4BA7-8E17-367B825FA721}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{BEC086F1-62CD-4BA7-8E17-367B825FA721}.Debug.ActiveCfg = Debug|Win32
|
||||
{BEC086F1-62CD-4BA7-8E17-367B825FA721}.Debug.Build.0 = Debug|Win32
|
||||
{BEC086F1-62CD-4BA7-8E17-367B825FA721}.Release.ActiveCfg = Release|Win32
|
||||
{BEC086F1-62CD-4BA7-8E17-367B825FA721}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Binary file not shown.
@@ -1,138 +0,0 @@
|
||||
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="Re2cTest"
|
||||
ProjectGUID="{BEC086F1-62CD-4BA7-8E17-367B825FA721}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/Re2cTest.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/Re2cTest.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
OmitFramePointers="TRUE"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/Re2cTest.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
|
||||
<File
|
||||
RelativePath="main.b.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="main.b.re">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Generate $(InputName).c from $(InputName).re using Re2c"
|
||||
CommandLine="..\..\..\Release\re2c.exe -b -o$(InputName).c $(InputName).re"
|
||||
Outputs="$(InputName).c"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Generate $(InputName).c from $(InputName).re using Re2c"
|
||||
CommandLine="..\..\..\Release\re2c.exe -b -o$(InputName).c $(InputName).re"
|
||||
Outputs="$(InputName).c"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx">
|
||||
<File
|
||||
RelativePath="HiResTimer.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,452 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "main.b.re"
|
||||
/* re2c lesson 001_upn_calculator, main.b.re, (c) M. Boerger, L. Allan 2006 */
|
||||
#line 43 "main.b.re"
|
||||
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#if _MSC_VER > 1200
|
||||
#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
|
||||
#endif // Prevents warning from vc7.1 complaining about redefinition
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include "HiResTimer.h"
|
||||
|
||||
static char gTestBuf[1000] = "";
|
||||
|
||||
/**
|
||||
* @brief Setup HiResolution timer and confirm it is working ok
|
||||
*/
|
||||
void InitHiResTimerAndVerifyWorking(void)
|
||||
{
|
||||
double elapsed;
|
||||
HrtInit();
|
||||
HrtSetPriority(ABOVE_NORMAL_PRIORITY_CLASS);
|
||||
HrtStart();
|
||||
Sleep(100);
|
||||
elapsed = HrtElapsedMillis();
|
||||
if ((elapsed < 90) || (elapsed > 110)) {
|
||||
printf("HiResTimer misbehaving: %f\n", elapsed);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scan for numbers in different formats
|
||||
*/
|
||||
int ScanFullSpeed(char *pzStrToScan, size_t lenStrToScan)
|
||||
{
|
||||
unsigned char *pzCurScanPos = (unsigned char*)pzStrToScan;
|
||||
unsigned char *pzBacktrackInfo = 0;
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR pzCurScanPos
|
||||
#define YYLIMIT (pzStrToScan+lenStrToScan)
|
||||
#define YYMARKER pzBacktrackInfo
|
||||
#define YYFILL(n)
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
#line 55 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
static const unsigned char yybm[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
128, 128, 128, 128, 128, 128, 128, 128,
|
||||
128, 128, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= ',') {
|
||||
if (yych <= 0x00) goto yy10;
|
||||
if (yych == '+') goto yy6;
|
||||
goto yy12;
|
||||
} else {
|
||||
if (yych <= '/') {
|
||||
if (yych <= '-') goto yy8;
|
||||
goto yy12;
|
||||
} else {
|
||||
if (yych <= '0') goto yy4;
|
||||
if (yych >= ':') goto yy12;
|
||||
}
|
||||
}
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy17;
|
||||
yy3:
|
||||
#line 93 "main.b.re"
|
||||
{ continue; }
|
||||
#line 114 "<stdout>"
|
||||
yy4:
|
||||
++YYCURSOR;
|
||||
if (yybm[0+(yych = *YYCURSOR)] & 128) {
|
||||
goto yy13;
|
||||
}
|
||||
yy5:
|
||||
#line 98 "main.b.re"
|
||||
{ return 1; }
|
||||
#line 123 "<stdout>"
|
||||
yy6:
|
||||
++YYCURSOR;
|
||||
#line 95 "main.b.re"
|
||||
{ continue; }
|
||||
#line 128 "<stdout>"
|
||||
yy8:
|
||||
++YYCURSOR;
|
||||
#line 96 "main.b.re"
|
||||
{ continue; }
|
||||
#line 133 "<stdout>"
|
||||
yy10:
|
||||
++YYCURSOR;
|
||||
#line 97 "main.b.re"
|
||||
{ return 0; }
|
||||
#line 138 "<stdout>"
|
||||
yy12:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy5;
|
||||
yy13:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy13;
|
||||
}
|
||||
#line 94 "main.b.re"
|
||||
{ continue; }
|
||||
#line 151 "<stdout>"
|
||||
yy16:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy17:
|
||||
if (yych <= '/') goto yy3;
|
||||
if (yych <= '9') goto yy16;
|
||||
goto yy3;
|
||||
}
|
||||
#line 99 "main.b.re"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scan for numbers in different formats
|
||||
*/
|
||||
int scan(char *pzStrToScan, size_t lenStrToScan)
|
||||
{
|
||||
unsigned char *pzCurScanPos = (unsigned char*)pzStrToScan;
|
||||
unsigned char *pzBacktrackInfo = 0;
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR pzCurScanPos
|
||||
#define YYLIMIT (pzStrToScan+lenStrToScan)
|
||||
#define YYMARKER pzBacktrackInfo
|
||||
#define YYFILL(n)
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
#line 182 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
static const unsigned char yybm[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
128, 128, 128, 128, 128, 128, 128, 128,
|
||||
128, 128, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= ',') {
|
||||
if (yych <= 0x00) goto yy28;
|
||||
if (yych == '+') goto yy24;
|
||||
goto yy30;
|
||||
} else {
|
||||
if (yych <= '/') {
|
||||
if (yych <= '-') goto yy26;
|
||||
goto yy30;
|
||||
} else {
|
||||
if (yych <= '0') goto yy22;
|
||||
if (yych >= ':') goto yy30;
|
||||
}
|
||||
}
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy35;
|
||||
yy21:
|
||||
#line 120 "main.b.re"
|
||||
{ printf("Num\n"); strcat(gTestBuf, "Num "); continue; }
|
||||
#line 240 "<stdout>"
|
||||
yy22:
|
||||
++YYCURSOR;
|
||||
if (yybm[0+(yych = *YYCURSOR)] & 128) {
|
||||
goto yy31;
|
||||
}
|
||||
yy23:
|
||||
#line 125 "main.b.re"
|
||||
{ printf("ERR\n"); strcat(gTestBuf, "ERR "); return 1; }
|
||||
#line 249 "<stdout>"
|
||||
yy24:
|
||||
++YYCURSOR;
|
||||
#line 122 "main.b.re"
|
||||
{ printf("+\n"); strcat(gTestBuf, "+ "); continue; }
|
||||
#line 254 "<stdout>"
|
||||
yy26:
|
||||
++YYCURSOR;
|
||||
#line 123 "main.b.re"
|
||||
{ printf("-\n"); strcat(gTestBuf, "- "); continue; }
|
||||
#line 259 "<stdout>"
|
||||
yy28:
|
||||
++YYCURSOR;
|
||||
#line 124 "main.b.re"
|
||||
{ printf("EOF\n"); return 0; }
|
||||
#line 264 "<stdout>"
|
||||
yy30:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy23;
|
||||
yy31:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy31;
|
||||
}
|
||||
#line 121 "main.b.re"
|
||||
{ printf("Oct\n"); strcat(gTestBuf, "Oct "); continue; }
|
||||
#line 277 "<stdout>"
|
||||
yy34:
|
||||
++YYCURSOR;
|
||||
if (YYLIMIT <= YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy35:
|
||||
if (yych <= '/') goto yy21;
|
||||
if (yych <= '9') goto yy34;
|
||||
goto yy21;
|
||||
}
|
||||
#line 126 "main.b.re"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Show high resolution elapsed time for 10,000 and 100,000 loops
|
||||
*/
|
||||
void DoTimingsOfStrnCmp(void)
|
||||
{
|
||||
char testStr[] = "Hello, world";
|
||||
int totLoops = 10000;
|
||||
int totFoundCount = 0;
|
||||
int foundCount = 0;
|
||||
int loop;
|
||||
int rc;
|
||||
const int progressAnd = 0xFFFFF000;
|
||||
double elapsed;
|
||||
|
||||
printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
|
||||
|
||||
HrtStart();
|
||||
for (loop = 0; loop < totLoops; ++loop) {
|
||||
foundCount = 0;
|
||||
rc = strncmp(testStr, "Hello", 5);
|
||||
if (rc == 0) {
|
||||
foundCount++;
|
||||
totFoundCount++;
|
||||
if ((totFoundCount & progressAnd) == totFoundCount) {
|
||||
printf("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsed = HrtElapsedMillis();
|
||||
printf("\nstrncmp Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
|
||||
printf("FoundCount each loop: %d\n", foundCount);
|
||||
printf("TotalFoundCount for all loops: %d\n", totFoundCount);
|
||||
|
||||
totLoops = 100000;
|
||||
HrtStart();
|
||||
for (loop = 0; loop < totLoops; ++loop) {
|
||||
foundCount = 0;
|
||||
rc = strncmp(testStr, "Hello", 5);
|
||||
if (rc == 0) {
|
||||
foundCount++;
|
||||
totFoundCount++;
|
||||
if ((totFoundCount & progressAnd) == totFoundCount) {
|
||||
printf("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsed = HrtElapsedMillis();
|
||||
printf("\nstrncmp Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
|
||||
printf("FoundCount each loop: %d\n", foundCount);
|
||||
printf("TotalFoundCount for all loops: %d\n", totFoundCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Show high resolution elapsed time for 10,000 and 100,000 loops
|
||||
*/
|
||||
void DoTimingsOfRe2c(void)
|
||||
{
|
||||
char* testStrings[] = { "123", "1234", "+123", "01234", "-04321", "abc", "123abc" };
|
||||
const int testCount = sizeof(testStrings) / sizeof(testStrings[0]);
|
||||
int i;
|
||||
int totLoops = 10000 / testCount; // Doing more than one per loop
|
||||
int totFoundCount = 0;
|
||||
int foundCount = 0;
|
||||
int loop;
|
||||
int rc;
|
||||
const int progressAnd = 0xFFFFF000;
|
||||
double elapsed;
|
||||
|
||||
printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
|
||||
|
||||
HrtStart();
|
||||
for (loop = 0; loop < totLoops; ++loop) {
|
||||
foundCount = 0;
|
||||
strcpy(gTestBuf, "");
|
||||
for (i = 0; i < testCount; ++i) {
|
||||
char* pzCurStr = testStrings[i];
|
||||
size_t len = strlen(pzCurStr); // Calc of strlen slows things down ... std::string?
|
||||
rc = ScanFullSpeed(pzCurStr, len);
|
||||
if (rc == 0) {
|
||||
foundCount++;
|
||||
totFoundCount++;
|
||||
if ((totFoundCount & progressAnd) == totFoundCount) {
|
||||
printf("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsed = HrtElapsedMillis();
|
||||
printf("\nRe2c Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
|
||||
printf("FoundCount each loop: %d\n", foundCount);
|
||||
printf("TotalFoundCount for all loops: %d\n", totFoundCount);
|
||||
|
||||
totLoops = 100000 / testCount;
|
||||
printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
|
||||
|
||||
HrtStart();
|
||||
for (loop = 0; loop < totLoops; ++loop) {
|
||||
foundCount = 0;
|
||||
strcpy(gTestBuf, "");
|
||||
for (i = 0; i < testCount; ++i) {
|
||||
char* pzCurStr = testStrings[i];
|
||||
size_t len = strlen(pzCurStr); // Calc of strlen slows things down ... std::string?
|
||||
rc = ScanFullSpeed(pzCurStr, len);
|
||||
if (rc == 0) {
|
||||
foundCount++;
|
||||
totFoundCount++;
|
||||
if ((totFoundCount & progressAnd) == totFoundCount) {
|
||||
printf("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsed = HrtElapsedMillis();
|
||||
printf("\nRe2c Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
|
||||
printf("FoundCount each loop: %d\n", foundCount);
|
||||
printf("TotalFoundCount for all loops: %d\n", totFoundCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Entry point for console app
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char testStr_A[] = "123";
|
||||
char* testStr_B = "456";
|
||||
char* testStrings[] = { "123", "1234", "+123", "01234", "-04321", "abc", "123abc" };
|
||||
const int testCount = sizeof(testStrings) / sizeof(testStrings[0]);
|
||||
int i;
|
||||
|
||||
int rc = scan(testStr_A, 3);
|
||||
printf("rc: %d\n", rc);
|
||||
|
||||
rc = scan(testStr_B, 3);
|
||||
printf("rc: %d\n", rc);
|
||||
|
||||
rc = scan("789", 3);
|
||||
printf("rc: %d\n", rc);
|
||||
|
||||
strcpy(gTestBuf, "");
|
||||
for (i = 0; i < testCount; ++i) {
|
||||
char* pzCurStr = testStrings[i];
|
||||
size_t len = strlen(pzCurStr);
|
||||
scan(pzCurStr, len);
|
||||
}
|
||||
printf("%s\n", gTestBuf);
|
||||
rc = strcmp(gTestBuf, "Num Num + Num Oct - Oct ERR Num ERR ");
|
||||
if (rc == 0) {
|
||||
printf("Success\n");
|
||||
}
|
||||
else {
|
||||
printf("Failure\n");
|
||||
}
|
||||
assert(0 == rc); // Doesn't work with Release build
|
||||
|
||||
InitHiResTimerAndVerifyWorking();
|
||||
|
||||
DoTimingsOfStrnCmp();
|
||||
|
||||
DoTimingsOfRe2c();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,291 +0,0 @@
|
||||
/* re2c lesson 001_upn_calculator, main.b.re, (c) M. Boerger, L. Allan 2006 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- basic interface for string reading
|
||||
|
||||
. We define the macros YYCTYPE, YYCURSOR, YYLIMIT, YYMARKER, YYFILL
|
||||
. YYCTYPE is the type re2c operates on or in other words the type that
|
||||
it generates code for. While it is not a big difference when we were
|
||||
using 'unsigned char' here we would need to run re2c with option -w
|
||||
to fully support types with sieof() > 1.
|
||||
. YYCURSOR is used internally and holds the current scanner position. In
|
||||
expression handlers, the code blocks after re2c expressions, this can be
|
||||
used to identify the end of the token.
|
||||
. YYMARKER is not always being used so we set an initial value to avoid
|
||||
a compiler warning.
|
||||
. YYLIMIT stores the end of the input. Unfortunatley we have to use strlen()
|
||||
in this lesson. In the next example we see one way to get rid of it.
|
||||
. We use a 'for(;;)'-loop around the scanner block. We could have used a
|
||||
'while(1)'-loop instead but some compilers generate a warning for it.
|
||||
. To make the output more readable we use 're2c:indent:top' scanner
|
||||
configuration that configures re2c to prepend a single tab (the default)
|
||||
to the beginning of each output line.
|
||||
. The following lines are expressions and for each expression we output the
|
||||
token name and continue the scanner loop.
|
||||
. The second last token detects the end of our input, the terminating zero in
|
||||
our input string. In other scanners detecting the end of input may vary.
|
||||
For example binary code may contain \0 as valid input.
|
||||
. The last expression accepts any input character. It tells re2c to accept
|
||||
the opposit of the empty range. This includes numbers and our tokens but
|
||||
as re2c goes from top to botton when evaluating the expressions this is no
|
||||
problem.
|
||||
. The first three rules show that re2c actually prioritizes the expressions
|
||||
from top to bottom. Octal number require a starting "0" and the actual
|
||||
number. Normal numbers start with a digit greater 0. And zero is finally a
|
||||
special case. A single "0" is detected by the last rule of this set. And
|
||||
valid ocal number is already being detected by the first rule. This even
|
||||
includes multi "0" sequences that in octal notation also means zero.
|
||||
Another way would be to only use two rules:
|
||||
"0" [0-9]+
|
||||
"0" | ( [1-9] [0-9]* )
|
||||
A full description of re2c rule syntax can be found in the manual.
|
||||
*/
|
||||
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#if _MSC_VER > 1200
|
||||
#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
|
||||
#endif // Prevents warning from vc7.1 complaining about redefinition
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include "HiResTimer.h"
|
||||
|
||||
static char gTestBuf[1000] = "";
|
||||
|
||||
/**
|
||||
* @brief Setup HiResolution timer and confirm it is working ok
|
||||
*/
|
||||
void InitHiResTimerAndVerifyWorking(void)
|
||||
{
|
||||
double elapsed;
|
||||
HrtInit();
|
||||
HrtSetPriority(ABOVE_NORMAL_PRIORITY_CLASS);
|
||||
HrtStart();
|
||||
Sleep(100);
|
||||
elapsed = HrtElapsedMillis();
|
||||
if ((elapsed < 90) || (elapsed > 110)) {
|
||||
printf("HiResTimer misbehaving: %f\n", elapsed);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scan for numbers in different formats
|
||||
*/
|
||||
int ScanFullSpeed(char *pzStrToScan, size_t lenStrToScan)
|
||||
{
|
||||
unsigned char *pzCurScanPos = (unsigned char*)pzStrToScan;
|
||||
unsigned char *pzBacktrackInfo = 0;
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR pzCurScanPos
|
||||
#define YYLIMIT (pzStrToScan+lenStrToScan)
|
||||
#define YYMARKER pzBacktrackInfo
|
||||
#define YYFILL(n)
|
||||
|
||||
for(;;)
|
||||
{
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
[1-9][0-9]* { continue; }
|
||||
[0][0-9]+ { continue; }
|
||||
"+" { continue; }
|
||||
"-" { continue; }
|
||||
"\000" { return 0; }
|
||||
[^] { return 1; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scan for numbers in different formats
|
||||
*/
|
||||
int scan(char *pzStrToScan, size_t lenStrToScan)
|
||||
{
|
||||
unsigned char *pzCurScanPos = (unsigned char*)pzStrToScan;
|
||||
unsigned char *pzBacktrackInfo = 0;
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR pzCurScanPos
|
||||
#define YYLIMIT (pzStrToScan+lenStrToScan)
|
||||
#define YYMARKER pzBacktrackInfo
|
||||
#define YYFILL(n)
|
||||
|
||||
for(;;)
|
||||
{
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
[1-9][0-9]* { printf("Num\n"); strcat(gTestBuf, "Num "); continue; }
|
||||
[0][0-9]+ { printf("Oct\n"); strcat(gTestBuf, "Oct "); continue; }
|
||||
"+" { printf("+\n"); strcat(gTestBuf, "+ "); continue; }
|
||||
"-" { printf("-\n"); strcat(gTestBuf, "- "); continue; }
|
||||
"\000" { printf("EOF\n"); return 0; }
|
||||
[^] { printf("ERR\n"); strcat(gTestBuf, "ERR "); return 1; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Show high resolution elapsed time for 10,000 and 100,000 loops
|
||||
*/
|
||||
void DoTimingsOfStrnCmp(void)
|
||||
{
|
||||
char testStr[] = "Hello, world";
|
||||
int totLoops = 10000;
|
||||
int totFoundCount = 0;
|
||||
int foundCount = 0;
|
||||
int loop;
|
||||
int rc;
|
||||
const int progressAnd = 0xFFFFF000;
|
||||
double elapsed;
|
||||
|
||||
printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
|
||||
|
||||
HrtStart();
|
||||
for (loop = 0; loop < totLoops; ++loop) {
|
||||
foundCount = 0;
|
||||
rc = strncmp(testStr, "Hello", 5);
|
||||
if (rc == 0) {
|
||||
foundCount++;
|
||||
totFoundCount++;
|
||||
if ((totFoundCount & progressAnd) == totFoundCount) {
|
||||
printf("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsed = HrtElapsedMillis();
|
||||
printf("\nstrncmp Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
|
||||
printf("FoundCount each loop: %d\n", foundCount);
|
||||
printf("TotalFoundCount for all loops: %d\n", totFoundCount);
|
||||
|
||||
totLoops = 100000;
|
||||
HrtStart();
|
||||
for (loop = 0; loop < totLoops; ++loop) {
|
||||
foundCount = 0;
|
||||
rc = strncmp(testStr, "Hello", 5);
|
||||
if (rc == 0) {
|
||||
foundCount++;
|
||||
totFoundCount++;
|
||||
if ((totFoundCount & progressAnd) == totFoundCount) {
|
||||
printf("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsed = HrtElapsedMillis();
|
||||
printf("\nstrncmp Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
|
||||
printf("FoundCount each loop: %d\n", foundCount);
|
||||
printf("TotalFoundCount for all loops: %d\n", totFoundCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Show high resolution elapsed time for 10,000 and 100,000 loops
|
||||
*/
|
||||
void DoTimingsOfRe2c(void)
|
||||
{
|
||||
char* testStrings[] = { "123", "1234", "+123", "01234", "-04321", "abc", "123abc" };
|
||||
const int testCount = sizeof(testStrings) / sizeof(testStrings[0]);
|
||||
int i;
|
||||
int totLoops = 10000 / testCount; // Doing more than one per loop
|
||||
int totFoundCount = 0;
|
||||
int foundCount = 0;
|
||||
int loop;
|
||||
int rc;
|
||||
const int progressAnd = 0xFFFFF000;
|
||||
double elapsed;
|
||||
|
||||
printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
|
||||
|
||||
HrtStart();
|
||||
for (loop = 0; loop < totLoops; ++loop) {
|
||||
foundCount = 0;
|
||||
strcpy(gTestBuf, "");
|
||||
for (i = 0; i < testCount; ++i) {
|
||||
char* pzCurStr = testStrings[i];
|
||||
size_t len = strlen(pzCurStr); // Calc of strlen slows things down ... std::string?
|
||||
rc = ScanFullSpeed(pzCurStr, len);
|
||||
if (rc == 0) {
|
||||
foundCount++;
|
||||
totFoundCount++;
|
||||
if ((totFoundCount & progressAnd) == totFoundCount) {
|
||||
printf("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsed = HrtElapsedMillis();
|
||||
printf("\nRe2c Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
|
||||
printf("FoundCount each loop: %d\n", foundCount);
|
||||
printf("TotalFoundCount for all loops: %d\n", totFoundCount);
|
||||
|
||||
totLoops = 100000 / testCount;
|
||||
printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
|
||||
|
||||
HrtStart();
|
||||
for (loop = 0; loop < totLoops; ++loop) {
|
||||
foundCount = 0;
|
||||
strcpy(gTestBuf, "");
|
||||
for (i = 0; i < testCount; ++i) {
|
||||
char* pzCurStr = testStrings[i];
|
||||
size_t len = strlen(pzCurStr); // Calc of strlen slows things down ... std::string?
|
||||
rc = ScanFullSpeed(pzCurStr, len);
|
||||
if (rc == 0) {
|
||||
foundCount++;
|
||||
totFoundCount++;
|
||||
if ((totFoundCount & progressAnd) == totFoundCount) {
|
||||
printf("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsed = HrtElapsedMillis();
|
||||
printf("\nRe2c Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
|
||||
printf("FoundCount each loop: %d\n", foundCount);
|
||||
printf("TotalFoundCount for all loops: %d\n", totFoundCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Entry point for console app
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char testStr_A[] = "123";
|
||||
char* testStr_B = "456";
|
||||
char* testStrings[] = { "123", "1234", "+123", "01234", "-04321", "abc", "123abc" };
|
||||
const int testCount = sizeof(testStrings) / sizeof(testStrings[0]);
|
||||
int i;
|
||||
|
||||
int rc = scan(testStr_A, 3);
|
||||
printf("rc: %d\n", rc);
|
||||
|
||||
rc = scan(testStr_B, 3);
|
||||
printf("rc: %d\n", rc);
|
||||
|
||||
rc = scan("789", 3);
|
||||
printf("rc: %d\n", rc);
|
||||
|
||||
strcpy(gTestBuf, "");
|
||||
for (i = 0; i < testCount; ++i) {
|
||||
char* pzCurStr = testStrings[i];
|
||||
size_t len = strlen(pzCurStr);
|
||||
scan(pzCurStr, len);
|
||||
}
|
||||
printf("%s\n", gTestBuf);
|
||||
rc = strcmp(gTestBuf, "Num Num + Num Oct - Oct ERR Num ERR ");
|
||||
if (rc == 0) {
|
||||
printf("Success\n");
|
||||
}
|
||||
else {
|
||||
printf("Failure\n");
|
||||
}
|
||||
assert(0 == rc); // Doesn't work with Release build
|
||||
|
||||
InitHiResTimerAndVerifyWorking();
|
||||
|
||||
DoTimingsOfStrnCmp();
|
||||
|
||||
DoTimingsOfRe2c();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
re2c lesson 002_strip_comments, (c) M. Boerger 2006
|
||||
|
||||
In this lesson you will learn how to use multiple scanner blocks and how to
|
||||
read the input from a file instead of a zero terminated string. In the end you
|
||||
will have a scanner that filters comments out of c source files but keeps re2c
|
||||
comments.
|
||||
|
||||
The first scanner can be generated with:
|
||||
|
||||
re2c -s -o t.c strip_001.s.re
|
||||
|
||||
In the second step we will learn about YYMARKER that stores backtracking
|
||||
information.
|
||||
|
||||
re2c -s -0 t.c strip_002.b.re
|
||||
|
||||
The third step brings trailing contexts that are stored in YYCTXMARKER. We also
|
||||
change to use -b instead of -s option since the scanner gets more and more
|
||||
complex.
|
||||
|
||||
re2c -b -0 t.c strip_002.b.re
|
||||
@@ -1,187 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "strip_001.s.re"
|
||||
/* re2c lesson 002_strip_comments, strip_001.s, (c) M. Boerger 2006 - 2007 */
|
||||
#line 32 "strip_001.s.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define YYMAXFILL 2
|
||||
#define BSIZE 128
|
||||
|
||||
#if BSIZE < YYMAXFILL
|
||||
# error BSIZE must be greater YYMAXFILL
|
||||
#endif
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR s.cur
|
||||
#define YYLIMIT s.lim
|
||||
#define YYFILL(n) { if ((res = fill(&s, n)) >= 0) break; }
|
||||
|
||||
typedef struct Scanner
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char *cur, *tok, *lim, *eof;
|
||||
unsigned char buffer[BSIZE];
|
||||
} Scanner;
|
||||
|
||||
int fill(Scanner *s, int len)
|
||||
{
|
||||
if (!len)
|
||||
{
|
||||
s->cur = s->tok = s->lim = s->buffer;
|
||||
s->eof = 0;
|
||||
}
|
||||
if (!s->eof)
|
||||
{
|
||||
int got, cnt = s->tok - s->buffer;
|
||||
|
||||
if (cnt > 0)
|
||||
{
|
||||
memcpy(s->buffer, s->tok, s->lim - s->tok);
|
||||
s->tok -= cnt;
|
||||
s->cur -= cnt;
|
||||
s->lim -= cnt;
|
||||
}
|
||||
cnt = BSIZE - cnt;
|
||||
if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt)
|
||||
{
|
||||
s->eof = &s->lim[got];
|
||||
}
|
||||
s->lim += got;
|
||||
}
|
||||
else if (s->cur + len > s->eof)
|
||||
{
|
||||
return 0; /* not enough input data */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int scan(FILE *fp)
|
||||
{
|
||||
int res = 0;
|
||||
Scanner s;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
return 1; /* no file was opened */
|
||||
}
|
||||
|
||||
s.fp = fp;
|
||||
|
||||
fill(&s, 0);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
s.tok = s.cur;
|
||||
|
||||
#line 80 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych != '/') goto yy4;
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) == '*') goto yy5;
|
||||
if (yych == '/') goto yy7;
|
||||
yy3:
|
||||
#line 113 "strip_001.s.re"
|
||||
{ fputc(*s.tok, stdout); continue; }
|
||||
#line 93 "<stdout>"
|
||||
yy4:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy3;
|
||||
yy5:
|
||||
++YYCURSOR;
|
||||
#line 112 "strip_001.s.re"
|
||||
{ goto comment; }
|
||||
#line 101 "<stdout>"
|
||||
yy7:
|
||||
++YYCURSOR;
|
||||
#line 111 "strip_001.s.re"
|
||||
{ goto cppcomment; }
|
||||
#line 106 "<stdout>"
|
||||
}
|
||||
#line 114 "strip_001.s.re"
|
||||
|
||||
comment:
|
||||
s.tok = s.cur;
|
||||
|
||||
#line 113 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych != '*') goto yy13;
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) == '/') goto yy14;
|
||||
yy12:
|
||||
#line 119 "strip_001.s.re"
|
||||
{ goto comment; }
|
||||
#line 124 "<stdout>"
|
||||
yy13:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy12;
|
||||
yy14:
|
||||
++YYCURSOR;
|
||||
#line 118 "strip_001.s.re"
|
||||
{ continue; }
|
||||
#line 132 "<stdout>"
|
||||
}
|
||||
#line 120 "strip_001.s.re"
|
||||
|
||||
cppcomment:
|
||||
s.tok = s.cur;
|
||||
|
||||
#line 139 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych == '\n') goto yy20;
|
||||
if (yych != '\r') goto yy22;
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) == '\n') goto yy23;
|
||||
yy19:
|
||||
#line 125 "strip_001.s.re"
|
||||
{ goto cppcomment; }
|
||||
#line 151 "<stdout>"
|
||||
yy20:
|
||||
++YYCURSOR;
|
||||
yy21:
|
||||
#line 124 "strip_001.s.re"
|
||||
{ fwrite(s.tok, 1, s.cur - s.tok, stdout); continue; }
|
||||
#line 157 "<stdout>"
|
||||
yy22:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy19;
|
||||
yy23:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy21;
|
||||
}
|
||||
#line 126 "strip_001.s.re"
|
||||
|
||||
}
|
||||
|
||||
if (fp != stdin)
|
||||
{
|
||||
fclose(fp); /* close only if not stdin */
|
||||
}
|
||||
return res; /* return result */
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
/* re2c lesson 002_strip_comments, strip_001.s, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- basic interface for file reading
|
||||
. This scanner will read chunks of input from a file. The easiest way would
|
||||
be to read the whole file into a memory buffer and use that a zero
|
||||
terminated string.
|
||||
. Instead we want to read input chunks of a reasonable size as they are neede
|
||||
by the scanner. Thus we basically need YYFILL(n) to call fread(n).
|
||||
. Before we provide a buffer that we constantly reallocate we instead use
|
||||
one buffer that we get from the stack or global memory just once. When we
|
||||
reach the end of the buffer we simply move the beginning of our input
|
||||
that is somewhere in our buffer to the beginning of our buffer and then
|
||||
append the next chunk of input to the correct end inside our buffer.
|
||||
. As re2c scanners might read more than one character we need to ensure our
|
||||
buffer is long enough. We can use re2c to inform about the maximum size
|
||||
by placing a "!max:re2c" comment somewhere. This gets translated to a
|
||||
"#define YYMAXFILL <n>" line where <n> is the maximum length value. This
|
||||
define can be used as precompiler condition.
|
||||
|
||||
- multiple scanner blocks
|
||||
. We use a main scanner block that outputs every input character unless the
|
||||
input is two /s or a / followed by a *. In the latter two cases we switch
|
||||
to a special c++ comment and a comment block respectively.
|
||||
. Both special blocks simply detect their end ignore any other character.
|
||||
. The c++ block is a bit special. Since the terminating new line needs to
|
||||
be output and that can either be a new line or a carridge return followed
|
||||
by a new line.
|
||||
. In order to ensure that we do not read behind our buffer we reset the token
|
||||
pointer to the cursor on every scanner run.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*!max:re2c */
|
||||
#define BSIZE 128
|
||||
|
||||
#if BSIZE < YYMAXFILL
|
||||
# error BSIZE must be greater YYMAXFILL
|
||||
#endif
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR s.cur
|
||||
#define YYLIMIT s.lim
|
||||
#define YYFILL(n) { if ((res = fill(&s, n)) >= 0) break; }
|
||||
|
||||
typedef struct Scanner
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char *cur, *tok, *lim, *eof;
|
||||
unsigned char buffer[BSIZE];
|
||||
} Scanner;
|
||||
|
||||
int fill(Scanner *s, int len)
|
||||
{
|
||||
if (!len)
|
||||
{
|
||||
s->cur = s->tok = s->lim = s->buffer;
|
||||
s->eof = 0;
|
||||
}
|
||||
if (!s->eof)
|
||||
{
|
||||
int got, cnt = s->tok - s->buffer;
|
||||
|
||||
if (cnt > 0)
|
||||
{
|
||||
memcpy(s->buffer, s->tok, s->lim - s->tok);
|
||||
s->tok -= cnt;
|
||||
s->cur -= cnt;
|
||||
s->lim -= cnt;
|
||||
}
|
||||
cnt = BSIZE - cnt;
|
||||
if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt)
|
||||
{
|
||||
s->eof = &s->lim[got];
|
||||
}
|
||||
s->lim += got;
|
||||
}
|
||||
else if (s->cur + len > s->eof)
|
||||
{
|
||||
return 0; /* not enough input data */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int scan(FILE *fp)
|
||||
{
|
||||
int res = 0;
|
||||
Scanner s;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
return 1; /* no file was opened */
|
||||
}
|
||||
|
||||
s.fp = fp;
|
||||
|
||||
fill(&s, 0);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
s.tok = s.cur;
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
|
||||
NL = "\r"? "\n" ;
|
||||
ANY = [^] ;
|
||||
|
||||
"/" "/" { goto cppcomment; }
|
||||
"/" "*" { goto comment; }
|
||||
ANY { fputc(*s.tok, stdout); continue; }
|
||||
*/
|
||||
comment:
|
||||
s.tok = s.cur;
|
||||
/*!re2c
|
||||
"*" "/" { continue; }
|
||||
ANY { goto comment; }
|
||||
*/
|
||||
cppcomment:
|
||||
s.tok = s.cur;
|
||||
/*!re2c
|
||||
NL { fwrite(s.tok, 1, s.cur - s.tok, stdout); continue; }
|
||||
ANY { goto cppcomment; }
|
||||
*/
|
||||
}
|
||||
|
||||
if (fp != stdin)
|
||||
{
|
||||
fclose(fp); /* close only if not stdin */
|
||||
}
|
||||
return res; /* return result */
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
/* Generated by re2c */
|
||||
#line 1 "strip_002.s.re"
|
||||
/* re2c lesson 002_strip_comments, strip_002.s, (c) M. Boerger 2006 - 2007 */
|
||||
#line 32 "strip_002.s.re"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define YYMAXFILL 2
|
||||
#define BSIZE 128
|
||||
|
||||
#if BSIZE < YYMAXFILL
|
||||
# error BSIZE must be greater YYMAXFILL
|
||||
#endif
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR s.cur
|
||||
#define YYLIMIT s.lim
|
||||
#define YYMARKER s.mrk
|
||||
#define YYFILL(n) { if ((res = fill(&s, n)) >= 0) break; }
|
||||
|
||||
typedef struct Scanner
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char *cur, *tok, *lim, *eof, *mrk;
|
||||
unsigned char buffer[BSIZE];
|
||||
} Scanner;
|
||||
|
||||
int fill(Scanner *s, int len)
|
||||
{
|
||||
if (!len)
|
||||
{
|
||||
s->cur = s->tok = s->lim = s->mrk = s->buffer;
|
||||
s->eof = 0;
|
||||
}
|
||||
if (!s->eof)
|
||||
{
|
||||
int got, cnt = s->tok - s->buffer;
|
||||
|
||||
if (cnt > 0)
|
||||
{
|
||||
memcpy(s->buffer, s->tok, s->lim - s->tok);
|
||||
s->tok -= cnt;
|
||||
s->cur -= cnt;
|
||||
s->lim -= cnt;
|
||||
s->mrk -= cnt;
|
||||
}
|
||||
cnt = BSIZE - cnt;
|
||||
if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt)
|
||||
{
|
||||
s->eof = &s->lim[got];
|
||||
}
|
||||
s->lim += got;
|
||||
}
|
||||
else if (s->cur + len > s->eof)
|
||||
{
|
||||
return 0; /* not enough input data */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void echo(Scanner *s)
|
||||
{
|
||||
fwrite(s->tok, 1, s->cur - s->tok, stdout);
|
||||
}
|
||||
|
||||
int scan(FILE *fp)
|
||||
{
|
||||
int res = 0;
|
||||
Scanner s;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
return 1; /* no file was opened */
|
||||
}
|
||||
|
||||
s.fp = fp;
|
||||
|
||||
fill(&s, 0);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
s.tok = s.cur;
|
||||
|
||||
#line 87 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych != '/') goto yy4;
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) == '*') goto yy5;
|
||||
if (yych == '/') goto yy7;
|
||||
yy3:
|
||||
#line 121 "strip_002.s.re"
|
||||
{ fputc(*s.tok, stdout); continue; }
|
||||
#line 100 "<stdout>"
|
||||
yy4:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy3;
|
||||
yy5:
|
||||
++YYCURSOR;
|
||||
#line 120 "strip_002.s.re"
|
||||
{ goto comment; }
|
||||
#line 108 "<stdout>"
|
||||
yy7:
|
||||
++YYCURSOR;
|
||||
#line 119 "strip_002.s.re"
|
||||
{ goto cppcomment; }
|
||||
#line 113 "<stdout>"
|
||||
}
|
||||
#line 122 "strip_002.s.re"
|
||||
|
||||
comment:
|
||||
s.tok = s.cur;
|
||||
|
||||
#line 120 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych != '*') goto yy13;
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) == '/') goto yy14;
|
||||
yy12:
|
||||
#line 127 "strip_002.s.re"
|
||||
{ goto comment; }
|
||||
#line 131 "<stdout>"
|
||||
yy13:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy12;
|
||||
yy14:
|
||||
++YYCURSOR;
|
||||
#line 126 "strip_002.s.re"
|
||||
{ goto commentws; }
|
||||
#line 139 "<stdout>"
|
||||
}
|
||||
#line 128 "strip_002.s.re"
|
||||
|
||||
commentws:
|
||||
s.tok = s.cur;
|
||||
|
||||
#line 146 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych <= '\f') {
|
||||
if (yych <= 0x08) goto yy23;
|
||||
if (yych <= '\t') goto yy22;
|
||||
if (yych <= '\n') goto yy20;
|
||||
goto yy23;
|
||||
} else {
|
||||
if (yych <= '\r') goto yy18;
|
||||
if (yych == ' ') goto yy22;
|
||||
goto yy23;
|
||||
}
|
||||
yy18:
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) == '\n') goto yy25;
|
||||
yy19:
|
||||
#line 133 "strip_002.s.re"
|
||||
{ goto commentws; }
|
||||
#line 167 "<stdout>"
|
||||
yy20:
|
||||
++YYCURSOR;
|
||||
yy21:
|
||||
#line 132 "strip_002.s.re"
|
||||
{ echo(&s); continue; }
|
||||
#line 173 "<stdout>"
|
||||
yy22:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy19;
|
||||
yy23:
|
||||
++YYCURSOR;
|
||||
#line 134 "strip_002.s.re"
|
||||
{ echo(&s); continue; }
|
||||
#line 181 "<stdout>"
|
||||
yy25:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy21;
|
||||
}
|
||||
#line 135 "strip_002.s.re"
|
||||
|
||||
cppcomment:
|
||||
s.tok = s.cur;
|
||||
|
||||
#line 192 "<stdout>"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if (yych == '\n') goto yy30;
|
||||
if (yych != '\r') goto yy32;
|
||||
++YYCURSOR;
|
||||
if ((yych = *YYCURSOR) == '\n') goto yy33;
|
||||
yy29:
|
||||
#line 140 "strip_002.s.re"
|
||||
{ goto cppcomment; }
|
||||
#line 204 "<stdout>"
|
||||
yy30:
|
||||
++YYCURSOR;
|
||||
yy31:
|
||||
#line 139 "strip_002.s.re"
|
||||
{ echo(&s); continue; }
|
||||
#line 210 "<stdout>"
|
||||
yy32:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy29;
|
||||
yy33:
|
||||
++YYCURSOR;
|
||||
yych = *YYCURSOR;
|
||||
goto yy31;
|
||||
}
|
||||
#line 141 "strip_002.s.re"
|
||||
|
||||
}
|
||||
|
||||
if (fp != stdin)
|
||||
{
|
||||
fclose(fp); /* close only if not stdin */
|
||||
}
|
||||
return res; /* return result */
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/* re2c lesson 002_strip_comments, strip_002.s, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- complexity
|
||||
. When a comment is preceded by a new line and followed by whitespace and a
|
||||
new line then we can drop the trailing whitespace and new line.
|
||||
. Additional to what we strip out already what about two consecutive comment
|
||||
blocks? When two comments are only separated by whitespace we want to drop
|
||||
both. In other words when detecting the end of a comment block we need to
|
||||
check whether it is followed by only whitespace and the a new comment in
|
||||
which case we continue ignoring the input. If it is followed only by white
|
||||
space and a new line we strip out the new white space and new line. In any
|
||||
other case we start outputting all that follows.
|
||||
But we cannot simply use the following two rules:
|
||||
"*" "/" WS* "/" "*" { continue; }
|
||||
"*" "/" WS* NL { continue; }
|
||||
The main problem is that WS* can get bigger then our buffer, so we need a
|
||||
new scanner.
|
||||
. Meanwhile our scanner gets a bit more complex and we have to add two more
|
||||
things. First the scanner code now uses a YYMARKER to store backtracking
|
||||
information.
|
||||
|
||||
- backtracking information
|
||||
. When the scanner has two rules that can have the same beginning but a
|
||||
different ending then it needs to store the position that identifies the
|
||||
common part. This is called backtracking. As mentioned above re2c expects
|
||||
you to provide compiler define YYMARKER and a pointer variable.
|
||||
. When shifting buffer contents as done in our fill function the marker needs
|
||||
to be corrected, too.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*!max:re2c */
|
||||
#define BSIZE 128
|
||||
|
||||
#if BSIZE < YYMAXFILL
|
||||
# error BSIZE must be greater YYMAXFILL
|
||||
#endif
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR s.cur
|
||||
#define YYLIMIT s.lim
|
||||
#define YYMARKER s.mrk
|
||||
#define YYFILL(n) { if ((res = fill(&s, n)) >= 0) break; }
|
||||
|
||||
typedef struct Scanner
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char *cur, *tok, *lim, *eof, *mrk;
|
||||
unsigned char buffer[BSIZE];
|
||||
} Scanner;
|
||||
|
||||
int fill(Scanner *s, int len)
|
||||
{
|
||||
if (!len)
|
||||
{
|
||||
s->cur = s->tok = s->lim = s->mrk = s->buffer;
|
||||
s->eof = 0;
|
||||
}
|
||||
if (!s->eof)
|
||||
{
|
||||
int got, cnt = s->tok - s->buffer;
|
||||
|
||||
if (cnt > 0)
|
||||
{
|
||||
memcpy(s->buffer, s->tok, s->lim - s->tok);
|
||||
s->tok -= cnt;
|
||||
s->cur -= cnt;
|
||||
s->lim -= cnt;
|
||||
s->mrk -= cnt;
|
||||
}
|
||||
cnt = BSIZE - cnt;
|
||||
if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt)
|
||||
{
|
||||
s->eof = &s->lim[got];
|
||||
}
|
||||
s->lim += got;
|
||||
}
|
||||
else if (s->cur + len > s->eof)
|
||||
{
|
||||
return 0; /* not enough input data */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void echo(Scanner *s)
|
||||
{
|
||||
fwrite(s->tok, 1, s->cur - s->tok, stdout);
|
||||
}
|
||||
|
||||
int scan(FILE *fp)
|
||||
{
|
||||
int res = 0;
|
||||
Scanner s;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
return 1; /* no file was opened */
|
||||
}
|
||||
|
||||
s.fp = fp;
|
||||
|
||||
fill(&s, 0);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
s.tok = s.cur;
|
||||
/*!re2c
|
||||
re2c:indent:top = 2;
|
||||
|
||||
NL = "\r"? "\n" ;
|
||||
WS = [\r\n\t ] ;
|
||||
ANY = [^] ;
|
||||
|
||||
"/" "/" { goto cppcomment; }
|
||||
"/" "*" { goto comment; }
|
||||
ANY { fputc(*s.tok, stdout); continue; }
|
||||
*/
|
||||
comment:
|
||||
s.tok = s.cur;
|
||||
/*!re2c
|
||||
"*" "/" { goto commentws; }
|
||||
ANY { goto comment; }
|
||||
*/
|
||||
commentws:
|
||||
s.tok = s.cur;
|
||||
/*!re2c
|
||||
NL { echo(&s); continue; }
|
||||
WS { goto commentws; }
|
||||
ANY { echo(&s); continue; }
|
||||
*/
|
||||
cppcomment:
|
||||
s.tok = s.cur;
|
||||
/*!re2c
|
||||
NL { echo(&s); continue; }
|
||||
ANY { goto cppcomment; }
|
||||
*/
|
||||
}
|
||||
|
||||
if (fp != stdin)
|
||||
{
|
||||
fclose(fp); /* close only if not stdin */
|
||||
}
|
||||
return res; /* return result */
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s <expr>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user