mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
Merge remote-tracking branch 'remotes/zdoom/master'
# Conflicts: # src/win32/i_system.cpp # tools/re2c/re2c.vcproj
This commit is contained in:
commit
0678a469de
244 changed files with 26078 additions and 17357 deletions
|
@ -229,12 +229,21 @@ include_directories( ${OPENGL_INCLUDE_DIR} )
|
|||
|
||||
if( NOT NO_OPENAL )
|
||||
find_package( OpenAL )
|
||||
mark_as_advanced(CLEAR OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
|
||||
mark_as_advanced(CLEAR OPENAL_INCLUDE_DIR)
|
||||
if( NOT WIN32 )
|
||||
mark_as_advanced(CLEAR OPENAL_LIBRARY)
|
||||
endif()
|
||||
if( OPENAL_FOUND )
|
||||
include_directories( ${OPENAL_INCLUDE_DIR} )
|
||||
if( NOT WIN32 )
|
||||
set( ZDOOM_LIBS ${OPENAL_LIBRARY} ${ZDOOM_LIBS} )
|
||||
endif()
|
||||
else()
|
||||
if ( NOT WIN32 )
|
||||
set( NO_OPENAL ON )
|
||||
else()
|
||||
include_directories( ${OPENAL_INCLUDE_DIR} )
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -1372,11 +1381,14 @@ endif()
|
|||
|
||||
if( MSVC )
|
||||
option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF )
|
||||
set( LINKERSTUFF "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"" )
|
||||
if( ZDOOM_GENERATE_MAPFILE )
|
||||
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\" /MAP")
|
||||
else()
|
||||
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\"")
|
||||
set( LINKERSTUFF "${LINKERSTUFF} /MAP" )
|
||||
endif()
|
||||
if( NOT NO_OPENAL )
|
||||
set( LINKERSTUFF "${LINKERSTUFF} /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\"" )
|
||||
endif()
|
||||
set_target_properties(zdoom PROPERTIES LINK_FLAGS ${LINKERSTUFF})
|
||||
|
||||
add_custom_command(TARGET zdoom POST_BUILD
|
||||
COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$<TARGET_FILE:zdoom>\"\;\#1
|
||||
|
|
|
@ -105,6 +105,7 @@ DEFINE_SPECIAL(Scroll_Texture_Down, 103, -1, -1, 2)
|
|||
DEFINE_SPECIAL(Ceiling_CrushAndRaiseSilentDist, 104, 3, 5, 5)
|
||||
DEFINE_SPECIAL(Door_WaitRaise, 105, 4, 5, 5)
|
||||
DEFINE_SPECIAL(Door_WaitClose, 106, 4, 5, 5)
|
||||
DEFINE_SPECIAL(Line_SetPortalTarget, 107, 2, 2, 2)
|
||||
|
||||
DEFINE_SPECIAL(Light_ForceLightning, 109, 1, 1, 1)
|
||||
DEFINE_SPECIAL(Light_RaiseByValue, 110, 2, 2, 2)
|
||||
|
|
|
@ -1041,6 +1041,7 @@ public:
|
|||
SDWORD reactiontime; // if non 0, don't attack yet; used by
|
||||
// player to freeze a bit after teleporting
|
||||
SDWORD threshold; // if > 0, the target will be chased
|
||||
SDWORD DefThreshold; // [MC] Default threshold which the actor will reset its threshold to after switching targets
|
||||
// no matter what (even if shot)
|
||||
player_t *player; // only valid if type of APlayerPawn
|
||||
TObjPtr<AActor> LastLookActor; // Actor last looked for (if TIDtoHate != 0)
|
||||
|
|
|
@ -1236,3 +1236,16 @@ CCMD(secret)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCMD(angleconvtest)
|
||||
{
|
||||
Printf("Testing degrees to angle conversion:\n");
|
||||
for (double ang = -5 * 180.; ang < 5 * 180.; ang += 45.)
|
||||
{
|
||||
angle_t ang1 = FLOAT2ANGLE(ang);
|
||||
angle_t ang2 = (angle_t)(ang * (ANGLE_90 / 90.));
|
||||
angle_t ang3 = (angle_t)(int)(ang * (ANGLE_90 / 90.));
|
||||
Printf("Angle = %.5f: xs_RoundToInt = %08x, unsigned cast = %08x, signed cast = %08x\n",
|
||||
ang, ang1, ang2, ang3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2111,7 +2111,7 @@ static int PatchCodePtrs (int dummy)
|
|||
else
|
||||
{
|
||||
TArray<DWORD> &args = sym->Variants[0].ArgFlags;
|
||||
if (args.Size() != 0 && !(args[0] & VARF_Optional))
|
||||
if ((sym->Flags & (VARF_Method | VARF_Action)) != (VARF_Method | VARF_Action) || (args.Size() > 3 && !(args[3] & VARF_Optional)))
|
||||
{
|
||||
Printf("Frame %d: Incompatible code pointer '%s'\n", frame, Line2);
|
||||
sym = NULL;
|
||||
|
@ -2723,9 +2723,9 @@ static bool LoadDehSupp ()
|
|||
else
|
||||
{
|
||||
TArray<DWORD> &args = sym->Variants[0].ArgFlags;
|
||||
if (args.Size() > 3 && !(args[3] & VARF_Optional))
|
||||
if ((sym->Flags & (VARF_Method|VARF_Action)) != (VARF_Method | VARF_Action) || (args.Size() > 3 && !(args[3] & VARF_Optional)))
|
||||
{
|
||||
sc.ScriptMessage("Incompatible code pointer '%s' %d, %d", sc.String, args.Size(), args.Size() > 3? args[3] : 0);
|
||||
sc.ScriptMessage("Incompatible code pointer '%s'", sc.String);
|
||||
}
|
||||
}
|
||||
Actions.Push(sym);
|
||||
|
|
|
@ -1476,7 +1476,7 @@ void ParseCVarInfo()
|
|||
|
||||
bool D_AddFile (TArray<FString> &wadfiles, const char *file, bool check, int position)
|
||||
{
|
||||
if (file == NULL)
|
||||
if (file == NULL || *file == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1507,6 +1507,10 @@ bool D_AddFile (TArray<FString> &wadfiles, const char *file, bool check, int pos
|
|||
|
||||
void D_AddWildFile (TArray<FString> &wadfiles, const char *value)
|
||||
{
|
||||
if (value == NULL || *value == '\0')
|
||||
{
|
||||
return;
|
||||
}
|
||||
const char *wadfile = BaseFileSearch (value, ".wad");
|
||||
|
||||
if (wadfile != NULL)
|
||||
|
@ -1648,6 +1652,10 @@ static const char *BaseFileSearch (const char *file, const char *ext, bool lookf
|
|||
{
|
||||
static char wad[PATH_MAX];
|
||||
|
||||
if (file == NULL || *file == '\0')
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (lookfirstinprogdir)
|
||||
{
|
||||
mysnprintf (wad, countof(wad), "%s%s%s", progdir.GetChars(), progdir[progdir.Len() - 1] != '/' ? "/" : "", file);
|
||||
|
|
|
@ -894,7 +894,7 @@ void ReadCompatibleUserInfo(FArchive &arc, userinfo_t &info)
|
|||
|
||||
*static_cast<FStringCVar *>(info[NAME_Name]) = netname;
|
||||
*static_cast<FIntCVar *>(info[NAME_Team]) = team;
|
||||
*static_cast<FFloatCVar *>(info[NAME_Autoaim]) = (float)aimdist / ANGLE_1;
|
||||
*static_cast<FFloatCVar *>(info[NAME_Autoaim]) = ANGLE2FLOAT(aimdist);
|
||||
*static_cast<FIntCVar *>(info[NAME_Skin]) = skin;
|
||||
*static_cast<FIntCVar *>(info[NAME_Gender]) = gender;
|
||||
*static_cast<FBoolCVar *>(info[NAME_NeverSwitchOnPickup]) = neverswitch;
|
||||
|
|
|
@ -392,7 +392,7 @@ static void parseSector(FScanner &sc)
|
|||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
sec.planexform[sector_t::floor].angle = angle_t(sc.Float * ANGLE_90 / 90.);
|
||||
sec.planexform[sector_t::floor].angle = FLOAT2ANGLE(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("flooroffsetx"))
|
||||
{
|
||||
|
@ -416,7 +416,7 @@ static void parseSector(FScanner &sc)
|
|||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
sec.planexform[sector_t::ceiling].angle = angle_t(sc.Float * ANGLE_90 / 90.);
|
||||
sec.planexform[sector_t::ceiling].angle = FLOAT2ANGLE(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("ceilingoffsetx"))
|
||||
{
|
||||
|
|
|
@ -1473,9 +1473,9 @@ void FParser::SF_SetCamera(void)
|
|||
else
|
||||
{
|
||||
fixed_t pitch = fixedvalue(t_argv[3]);
|
||||
if(pitch < -50*FRACUNIT) pitch = -50*FRACUNIT;
|
||||
if(pitch > 50*FRACUNIT) pitch = 50*FRACUNIT;
|
||||
newcamera->pitch=(angle_t)((pitch/65536.0f)*(ANGLE_45/45.0f)*(20.0f/32.0f));
|
||||
if (pitch < -50 * FRACUNIT) pitch = -50 * FRACUNIT;
|
||||
if (pitch > 50 * FRACUNIT) pitch = 50 * FRACUNIT;
|
||||
newcamera->pitch = xs_CRoundToUInt((pitch / 65536.0f)*(ANGLE_45 / 45.0f)*(20.0f / 32.0f));
|
||||
}
|
||||
player->camera=newcamera;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack)
|
|||
if (fire != NULL)
|
||||
{
|
||||
// move the fire between the vile and the player
|
||||
fixedvec3 pos = target->Vec3Angle(-24 * FRACUNIT, self->angle, target->Z());
|
||||
fixedvec3 pos = target->Vec3Angle(-24 * FRACUNIT, self->angle, 0);
|
||||
fire->SetOrigin (pos, true);
|
||||
|
||||
P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0);
|
||||
|
|
|
@ -124,7 +124,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
|
|||
PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; }
|
||||
PARAM_INT_OPT (flags) { flags = 0; }
|
||||
PARAM_FIXED_OPT (range) { range = 0; }
|
||||
PARAM_ANGLE_OPT (spread_xy) { spread_xy = angle_t(2.8125 * (ANGLE_90 / 90.0)); }
|
||||
PARAM_ANGLE_OPT(spread_xy) { spread_xy = 33554432; /*angle_t(2.8125 * (ANGLE_90 / 90.0));*/ } // The floating point expression does not get optimized away.
|
||||
PARAM_ANGLE_OPT (spread_z) { spread_z = 0; }
|
||||
PARAM_FIXED_OPT (lifesteal) { lifesteal = 0; }
|
||||
PARAM_INT_OPT (lifestealmax) { lifestealmax = 0; }
|
||||
|
|
|
@ -72,7 +72,7 @@ bool AArtiTimeBomb::Use (bool pickup)
|
|||
{
|
||||
angle_t angle = Owner->angle >> ANGLETOFINESHIFT;
|
||||
AActor *mo = Spawn("ActivatedTimeBomb",
|
||||
Vec3Angle(24*FRACUNIT, Owner->angle, - Owner->floorclip), ALLOW_REPLACE);
|
||||
Owner->Vec3Angle(24*FRACUNIT, Owner->angle, - Owner->floorclip), ALLOW_REPLACE);
|
||||
mo->target = Owner;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -131,8 +131,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
|
|||
{
|
||||
mo->AddZ(-32*FRACUNIT, false);
|
||||
mo->tracer = target;
|
||||
mo->special1 = 60;
|
||||
mo->special2 = 50; // Timer for active sound
|
||||
mo->health = 20*TICRATE; // Duration
|
||||
S_Sound (self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM);
|
||||
}
|
||||
|
@ -158,9 +156,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_WhirlwindSeek)
|
|||
self->flags &= ~MF_MISSILE;
|
||||
return 0;
|
||||
}
|
||||
if ((self->special2 -= 3) < 0)
|
||||
if ((self->threshold -= 3) < 0)
|
||||
{
|
||||
self->special2 = 58 + (pr_seek() & 31);
|
||||
self->threshold = 58 + (pr_seek() & 31);
|
||||
S_Sound (self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM);
|
||||
}
|
||||
if (self->tracer && self->tracer->flags&MF_SHADOW)
|
||||
|
|
|
@ -86,7 +86,7 @@ void ASecurityCamera::PostBeginPlay ()
|
|||
pitch = -ANGLE_90 + ANGLE_1;
|
||||
else if (pitch >= ANGLE_90)
|
||||
pitch = ANGLE_90 - ANGLE_1;
|
||||
Range = (angle_t)((float)args[1] * 536870912.f / 45.f);
|
||||
Range = FLOAT2ANGLE(args[1]);
|
||||
}
|
||||
|
||||
void ASecurityCamera::Tick ()
|
||||
|
@ -136,7 +136,7 @@ void AAimingCamera::PostBeginPlay ()
|
|||
|
||||
args[2] = 0;
|
||||
Super::PostBeginPlay ();
|
||||
MaxPitchChange = (int)((float)changepitch * 536870912.f / 45.f / (float)TICRATE);
|
||||
MaxPitchChange = FLOAT2ANGLE(changepitch * TICRATE);
|
||||
Range /= TICRATE;
|
||||
|
||||
TActorIterator<AActor> iterator (args[3]);
|
||||
|
@ -181,7 +181,7 @@ void AAimingCamera::Tick ()
|
|||
double dz = Z() - tracer->Z() - tracer->height/2;
|
||||
double dist = vect.Length();
|
||||
double ang = dist != 0.f ? atan2 (dz, dist) : 0;
|
||||
int desiredpitch = (angle_t)(ang * 2147483648.f / PI);
|
||||
int desiredpitch = (int)RAD2ANGLE(ang);
|
||||
if (abs (desiredpitch - pitch) < MaxPitchChange)
|
||||
{
|
||||
pitch = desiredpitch;
|
||||
|
|
|
@ -430,12 +430,12 @@ bool APathFollower::Interpolate ()
|
|||
}
|
||||
if (args[2] & 4)
|
||||
{ // adjust pitch; use floats for precision
|
||||
float fdx = FIXED2FLOAT(dx);
|
||||
float fdy = FIXED2FLOAT(dy);
|
||||
float fdz = FIXED2FLOAT(-dz);
|
||||
float dist = (float)sqrt (fdx*fdx + fdy*fdy);
|
||||
float ang = dist != 0.f ? (float)atan2 (fdz, dist) : 0;
|
||||
pitch = (angle_t)(ang * 2147483648.f / PI);
|
||||
double fdx = FIXED2DBL(dx);
|
||||
double fdy = FIXED2DBL(dy);
|
||||
double fdz = FIXED2DBL(-dz);
|
||||
double dist = sqrt (fdx*fdx + fdy*fdy);
|
||||
double ang = dist != 0.f ? atan2 (fdz, dist) : 0;
|
||||
pitch = (fixed_t)RAD2ANGLE(ang);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -449,11 +449,11 @@ bool APathFollower::Interpolate ()
|
|||
float lerped = Lerp (angle1, angle2 + 4294967296.f);
|
||||
if (lerped >= 4294967296.f)
|
||||
{
|
||||
angle = (angle_t)(lerped - 4294967296.f);
|
||||
angle = xs_CRoundToUInt(lerped - 4294967296.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = (angle_t)lerped;
|
||||
angle = xs_CRoundToUInt(lerped);
|
||||
}
|
||||
}
|
||||
else if (angle2 - angle1 >= 2147483648.f)
|
||||
|
@ -461,16 +461,16 @@ bool APathFollower::Interpolate ()
|
|||
float lerped = Lerp (angle1, angle2 - 4294967296.f);
|
||||
if (lerped < 0.f)
|
||||
{
|
||||
angle = (angle_t)(lerped + 4294967296.f);
|
||||
angle = xs_CRoundToUInt(lerped + 4294967296.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = (angle_t)lerped;
|
||||
angle = xs_CRoundToUInt(lerped);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = (angle_t)Lerp (angle1, angle2);
|
||||
angle = xs_CRoundToUInt(Lerp (angle1, angle2));
|
||||
}
|
||||
}
|
||||
if (args[2] & 1)
|
||||
|
@ -677,7 +677,7 @@ bool AMovingCamera::Interpolate ()
|
|||
double dz = FIXED2DBL(Z() - tracer->Z() - tracer->height/2);
|
||||
double dist = sqrt (dx*dx + dy*dy);
|
||||
double ang = dist != 0.f ? atan2 (dz, dist) : 0;
|
||||
pitch = (angle_t)(ang * 2147483648.f / PI);
|
||||
pitch = RAD2ANGLE(ang);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -90,7 +90,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Beacon)
|
|||
self->flags &= ~MF_SPECIAL;
|
||||
static_cast<AInventory *>(self)->DropTime = 0;
|
||||
// Set up the new rebel.
|
||||
rebel->threshold = BASETHRESHOLD;
|
||||
rebel->threshold = rebel->DefThreshold;
|
||||
rebel->target = NULL;
|
||||
rebel->flags4 |= MF4_INCOMBAT;
|
||||
rebel->LastHeard = owner; // Make sure the rebels look for targets
|
||||
|
|
|
@ -141,4 +141,12 @@ inline SDWORD ModDiv (SDWORD num, SDWORD den, SDWORD *dmval)
|
|||
#define FIXED2FLOAT(f) ((f) / float(65536))
|
||||
#define FIXED2DBL(f) ((f) / double(65536))
|
||||
|
||||
#define ANGLE2DBL(f) ((f) * (90./ANGLE_90))
|
||||
#define ANGLE2FLOAT(f) (float((f) * (90./ANGLE_90)))
|
||||
#define FLOAT2ANGLE(f) ((angle_t)xs_CRoundToInt((f) * (ANGLE_90/90.)))
|
||||
|
||||
#define ANGLE2RAD(f) ((f) * (M_PI/ANGLE_180))
|
||||
#define ANGLE2RADF(f) ((f) * float(M_PI/ANGLE_180))
|
||||
#define RAD2ANGLE(f) ((angle_t)xs_CRoundToInt((f) * (ANGLE_180/M_PI)))
|
||||
|
||||
#endif
|
||||
|
|
|
@ -225,7 +225,7 @@ public:
|
|||
|
||||
void SetSelection(int Selection)
|
||||
{
|
||||
float f = fabs(SELECTED_JOYSTICK->GetAxisScale(mAxis));
|
||||
float f = fabsf(SELECTED_JOYSTICK->GetAxisScale(mAxis));
|
||||
if (Selection) f*=-1;
|
||||
SELECTED_JOYSTICK->SetAxisScale(mAxis, f);
|
||||
}
|
||||
|
|
|
@ -324,7 +324,12 @@ void FValueTextItem::Drawer(bool selected)
|
|||
screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
|
||||
|
||||
int x = mXpos + mFont->StringWidth(text) + 8;
|
||||
if (mSelections.Size() > 0) screen->DrawText(mFont, mFontColor2, x, mYpos, mSelections[mSelection], DTA_Clean, true, TAG_DONE);
|
||||
if (mSelections.Size() > 0)
|
||||
{
|
||||
const char *mOptValue = mSelections[mSelection];
|
||||
if (*mOptValue == '$') mOptValue = GStrings(mOptValue + 1);
|
||||
screen->DrawText(mFont, mFontColor2, x, mYpos, mOptValue, DTA_Clean, true, TAG_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -300,6 +300,8 @@ xx(Z)
|
|||
xx(MomX)
|
||||
xx(MomY)
|
||||
xx(MomZ)
|
||||
xx(Threshold)
|
||||
xx(DefThreshold)
|
||||
xx(Abs)
|
||||
xx(ACS_NamedExecuteWithResult)
|
||||
xx(CallACS)
|
||||
|
|
|
@ -4561,7 +4561,7 @@ bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *
|
|||
{
|
||||
PField *var = dyn_cast<PField>(self->GetClass()->Symbols.FindSymbol(varname, true));
|
||||
PArray *arraytype;
|
||||
BYTE *baddr = reinterpret_cast<BYTE *>(self);
|
||||
BYTE *baddr = reinterpret_cast<BYTE *>(self) + var->Offset;
|
||||
|
||||
if (var == NULL || (var->Flags & VARF_Native))
|
||||
{
|
||||
|
|
|
@ -1859,7 +1859,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
|
|||
|
||||
AActor *targ = NULL; // Shuts up gcc
|
||||
fixed_t dist;
|
||||
angle_t fov = (fov_f == 0) ? ANGLE_180 : angle_t(fov_f * ANGLE_90 / 90);
|
||||
angle_t fov = (fov_f == 0) ? ANGLE_180 : FLOAT2ANGLE(fov_f);
|
||||
FLookExParams params = { fov, minseedist, maxseedist, maxheardist, flags, seestate };
|
||||
|
||||
if (self->flags5 & MF5_INCONVERSATION)
|
||||
|
@ -2827,7 +2827,7 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch, a
|
|||
|
||||
double dist_z = target_z - source_z;
|
||||
double ddist = sqrt(dist.X*dist.X + dist.Y*dist.Y + dist_z*dist_z);
|
||||
int other_pitch = (int)rad2bam(asin(dist_z / ddist));
|
||||
int other_pitch = (int)RAD2ANGLE(asin(dist_z / ddist));
|
||||
|
||||
if (max_pitch != 0)
|
||||
{
|
||||
|
@ -2846,7 +2846,6 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch, a
|
|||
{
|
||||
self->pitch = other_pitch;
|
||||
}
|
||||
if (flags & FAF_NODISTFACTOR)
|
||||
self->pitch += pitch_offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -1511,7 +1511,7 @@ dopain:
|
|||
{
|
||||
if (source == target->target)
|
||||
{
|
||||
target->threshold = BASETHRESHOLD;
|
||||
target->threshold = target->DefThreshold;
|
||||
if (target->state == target->SpawnState && target->SeeState != NULL)
|
||||
{
|
||||
target->SetState (target->SeeState);
|
||||
|
@ -1532,7 +1532,7 @@ dopain:
|
|||
target->lastenemy = target->target; // remember last enemy - killough
|
||||
}
|
||||
target->target = source;
|
||||
target->threshold = BASETHRESHOLD;
|
||||
target->threshold = target->DefThreshold;
|
||||
if (target->state == target->SpawnState && target->SeeState != NULL)
|
||||
{
|
||||
target->SetState (target->SeeState);
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "d_net.h"
|
||||
#include "d_event.h"
|
||||
#include "gstrings.h"
|
||||
#include "portal.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "fragglescript/t_fs.h"
|
||||
|
||||
|
@ -3387,6 +3388,11 @@ FUNC(LS_Thing_SetConversation)
|
|||
return true;
|
||||
}
|
||||
|
||||
FUNC(LS_Line_SetPortalTarget)
|
||||
// Line_SetPortalTarget(thisid, destid)
|
||||
{
|
||||
return P_ChangePortal(ln, arg0, arg1);
|
||||
}
|
||||
|
||||
static lnSpecFunc LineSpecials[] =
|
||||
{
|
||||
|
@ -3497,7 +3503,7 @@ static lnSpecFunc LineSpecials[] =
|
|||
/* 104 */ LS_Ceiling_CrushAndRaiseSilentDist,
|
||||
/* 105 */ LS_Door_WaitRaise,
|
||||
/* 106 */ LS_Door_WaitClose,
|
||||
/* 107 */ LS_NOP,
|
||||
/* 107 */ LS_Line_SetPortalTarget,
|
||||
/* 108 */ LS_NOP,
|
||||
/* 109 */ LS_Light_ForceLightning,
|
||||
/* 110 */ LS_Light_RaiseByValue,
|
||||
|
|
|
@ -87,7 +87,8 @@ inline int GetSafeBlockY(long long blocky)
|
|||
#define PLAYERMISSILERANGE (8192*FRACUNIT) // [RH] New MISSILERANGE for players
|
||||
|
||||
// follow a player exlusively for 3 seconds
|
||||
#define BASETHRESHOLD 100
|
||||
// No longer used.
|
||||
// #define BASETHRESHOLD 100
|
||||
|
||||
|
||||
//
|
||||
|
|
|
@ -433,6 +433,10 @@ void AActor::Serialize (FArchive &arc)
|
|||
<< RipLevelMin
|
||||
<< RipLevelMax;
|
||||
}
|
||||
if (SaveVersion >= 4533)
|
||||
{
|
||||
arc << DefThreshold;
|
||||
}
|
||||
|
||||
{
|
||||
FString tagstr;
|
||||
|
@ -1349,7 +1353,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
|||
{
|
||||
if (mo->flags3 & MF3_EXPLOCOUNT)
|
||||
{
|
||||
if (++mo->special2 < mo->special1)
|
||||
if (++mo->threshold < mo->DefThreshold)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -260,7 +260,7 @@ fixed_t UDMFParserBase::CheckFixed(const char *key)
|
|||
|
||||
angle_t UDMFParserBase::CheckAngle(const char *key)
|
||||
{
|
||||
return angle_t(CheckFloat(key) * ANGLE_90 / 90.);
|
||||
return FLOAT2ANGLE(CheckFloat(key));
|
||||
}
|
||||
|
||||
bool UDMFParserBase::CheckBool(const char *key)
|
||||
|
|
|
@ -2305,7 +2305,7 @@ void P_PlayerThink (player_t *player)
|
|||
{
|
||||
// A negative scale is used to prevent G_AddViewAngle/G_AddViewPitch
|
||||
// from scaling with the FOV scale.
|
||||
desired *= fabs(player->ReadyWeapon->FOVScale);
|
||||
desired *= fabsf(player->ReadyWeapon->FOVScale);
|
||||
}
|
||||
if (player->FOV != desired)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,24 @@ FArchive &operator<< (FArchive &arc, FLinePortal &port)
|
|||
}
|
||||
|
||||
|
||||
static line_t *FindDestination(line_t *src, int tag)
|
||||
{
|
||||
if (tag)
|
||||
{
|
||||
int lineno = -1;
|
||||
FLineIdIterator it(tag);
|
||||
|
||||
while ((lineno = it.Next()) >= 0)
|
||||
{
|
||||
if (&lines[lineno] != src)
|
||||
{
|
||||
return &lines[lineno];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void P_SpawnLinePortal(line_t* line)
|
||||
{
|
||||
// portal destination is special argument #0
|
||||
|
@ -36,21 +54,7 @@ void P_SpawnLinePortal(line_t* line)
|
|||
|
||||
if (line->args[2] >= PORTT_VISUAL && line->args[2] <= PORTT_LINKED)
|
||||
{
|
||||
if (line->args[0] > 0)
|
||||
{
|
||||
int linenum = -1;
|
||||
|
||||
for (int i = 0; i < numlines; i++)
|
||||
{
|
||||
if (&lines[i] == line)
|
||||
continue;
|
||||
if (tagManager.LineHasID(&lines[i], line->args[0]))
|
||||
{
|
||||
dst = &lines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dst = FindDestination(line, line->args[0]);
|
||||
|
||||
line->portalindex = linePortals.Reserve(1);
|
||||
FLinePortal *port = &linePortals.Last();
|
||||
|
@ -156,6 +160,50 @@ void P_FinalizePortals()
|
|||
}
|
||||
}
|
||||
|
||||
static bool ChangePortalLine(line_t *line, int destid)
|
||||
{
|
||||
if (line->portalindex >= linePortals.Size()) return false;
|
||||
FLinePortal *port = &linePortals[line->portalindex];
|
||||
if (port->mType == PORTT_LINKED) return false; // linked portals cannot be changed.
|
||||
if (destid == 0) port->mDestination = NULL;
|
||||
port->mDestination = FindDestination(line, destid);
|
||||
if (port->mDestination == NULL)
|
||||
{
|
||||
port->mFlags = 0;
|
||||
}
|
||||
else if (port->mType == PORTT_INTERACTIVE)
|
||||
{
|
||||
FLinePortal *portd = &linePortals[port->mDestination->portalindex];
|
||||
if (portd != NULL && portd->mType == PORTT_INTERACTIVE && portd->mDestination == line)
|
||||
{
|
||||
// this is a 2-way interactive portal
|
||||
port->mFlags = port->mDefFlags | PORTF_INTERACTIVE;
|
||||
portd->mFlags = portd->mDefFlags | PORTF_INTERACTIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
port->mFlags = port->mDefFlags;
|
||||
portd->mFlags = portd->mDefFlags;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool P_ChangePortal(line_t *ln, int thisid, int destid)
|
||||
{
|
||||
int lineno;
|
||||
|
||||
if (thisid == 0) return ChangePortalLine(ln, destid);
|
||||
FLineIdIterator it(thisid);
|
||||
bool res = false;
|
||||
while ((lineno = it.Next()) >= 0)
|
||||
{
|
||||
res |= ChangePortalLine(&lines[lineno], destid);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// [ZZ] lots of floats here to avoid overflowing a lot
|
||||
bool P_IntersectLines(fixed_t o1x, fixed_t o1y, fixed_t p1x, fixed_t p1y,
|
||||
fixed_t o2x, fixed_t o2y, fixed_t p2x, fixed_t p2y,
|
||||
|
|
|
@ -52,6 +52,7 @@ extern TArray<FLinePortal> linePortals;
|
|||
|
||||
void P_SpawnLinePortal(line_t* line);
|
||||
void P_FinalizePortals();
|
||||
bool P_ChangePortal(line_t *ln, int thisid, int destid);
|
||||
|
||||
|
||||
/* code ported from prototype */
|
||||
|
|
|
@ -531,7 +531,7 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts)
|
|||
{
|
||||
sc.TokenMustBe(TK_FloatConst);
|
||||
}
|
||||
opts.AngleOffset = ANGLE_90 + angle_t(sc.Float * ANGLE_180 / 180.0);
|
||||
opts.AngleOffset = ANGLE_90 + FLOAT2ANGLE(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("overridepalette"))
|
||||
{
|
||||
|
|
|
@ -1531,7 +1531,7 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
yscale = pl->yscale << (16 - ds_ybits);
|
||||
if (planeang != 0)
|
||||
{
|
||||
double rad = bam2rad(planeang);
|
||||
double rad = ANGLE2RAD(planeang);
|
||||
double cosine = cos(rad), sine = sin(rad);
|
||||
|
||||
pviewx = xs_RoundToInt(pl->xoffs + viewx * cosine - viewy * sine);
|
||||
|
@ -1668,13 +1668,13 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
// p is the texture origin in view space
|
||||
// Don't add in the offsets at this stage, because doing so can result in
|
||||
// errors if the flat is rotated.
|
||||
ang = bam2rad(ANG270 - viewangle);
|
||||
ang = ANGLE2RAD(ANG270 - viewangle);
|
||||
p[0] = vx * cos(ang) - vy * sin(ang);
|
||||
p[2] = vx * sin(ang) + vy * cos(ang);
|
||||
p[1] = pl->height.ZatPoint(0.0, 0.0) - vz;
|
||||
|
||||
// m is the v direction vector in view space
|
||||
ang = bam2rad(ANG180 - viewangle - pl->angle);
|
||||
ang = ANGLE2RAD(ANG180 - viewangle - pl->angle);
|
||||
m[0] = yscale * cos(ang);
|
||||
m[2] = yscale * sin(ang);
|
||||
// m[1] = FIXED2FLOAT(pl->height.ZatPoint (0, iyscale) - pl->height.ZatPoint (0,0));
|
||||
|
@ -1690,7 +1690,7 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
// This code keeps the texture coordinates constant across the x,y plane no matter
|
||||
// how much you slope the surface. Use the commented-out code above instead to keep
|
||||
// the textures a constant size across the surface's plane instead.
|
||||
ang = bam2rad(pl->angle);
|
||||
ang = ANGLE2RAD(pl->angle);
|
||||
m[1] = pl->height.ZatPoint(vx + yscale * sin(ang), vy + yscale * cos(ang)) - zeroheight;
|
||||
ang += PI/2;
|
||||
n[1] = pl->height.ZatPoint(vx + xscale * sin(ang), vy + xscale * cos(ang)) - zeroheight;
|
||||
|
|
|
@ -1012,7 +1012,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
if (voxelspin != 0)
|
||||
{
|
||||
double ang = double(I_FPSTime()) * voxelspin / 1000;
|
||||
vis->angle -= angle_t(ang * (4294967296.f / 360));
|
||||
vis->angle -= FLOAT2ANGLE(ang);
|
||||
}
|
||||
|
||||
vis->vx = viewx;
|
||||
|
|
|
@ -1953,7 +1953,7 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor)
|
|||
{
|
||||
if (listenactor != NULL)
|
||||
{
|
||||
listener.angle = (float)(listenactor->angle) * ((float)PI / 2147483648.f);
|
||||
listener.angle = ANGLE2RADF(listenactor->angle);
|
||||
/*
|
||||
listener.velocity.X = listenactor->velx * (TICRATE/65536.f);
|
||||
listener.velocity.Y = listenactor->velz * (TICRATE/65536.f);
|
||||
|
|
|
@ -698,8 +698,8 @@ bool FMODSoundRenderer::Init()
|
|||
}
|
||||
|
||||
const char *wrongver = NULL;
|
||||
#if FMOD_VERSION >= 0x43800
|
||||
if (version < 0x43800)
|
||||
#if FMOD_VERSION >= 0x43600
|
||||
if (version < 0x43600)
|
||||
#else
|
||||
if (version < 0x42000)
|
||||
#endif
|
||||
|
@ -2311,9 +2311,9 @@ void FMODSoundRenderer::UpdateListener(SoundListener *listener)
|
|||
pos.z = listener->position.Z;
|
||||
|
||||
float angle = listener->angle;
|
||||
forward.x = cos(angle);
|
||||
forward.x = cosf(angle);
|
||||
forward.y = 0;
|
||||
forward.z = sin(angle);
|
||||
forward.z = sinf(angle);
|
||||
|
||||
up.x = 0;
|
||||
up.y = 1;
|
||||
|
@ -3135,7 +3135,7 @@ void FMODSoundRenderer::InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) co
|
|||
|
||||
FMOD_RESULT FMODSoundRenderer::SetSystemReverbProperties(const REVERB_PROPERTIES *props)
|
||||
{
|
||||
#if FMOD_VERSION < 0x43800
|
||||
#if FMOD_VERSION < 0x43600
|
||||
return Sys->setReverbProperties((const FMOD_REVERB_PROPERTIES *)props);
|
||||
#else
|
||||
// The reverb format changed when hardware mixing support was dropped, because
|
||||
|
|
|
@ -175,7 +175,7 @@ int WinMIDIDevice::GetTechnology() const
|
|||
|
||||
int WinMIDIDevice::SetTempo(int tempo)
|
||||
{
|
||||
MIDIPROPTEMPO data = { sizeof(MIDIPROPTEMPO), tempo };
|
||||
MIDIPROPTEMPO data = { sizeof(MIDIPROPTEMPO), (DWORD)tempo };
|
||||
return midiStreamProperty(MidiOut, (LPBYTE)&data, MIDIPROP_SET | MIDIPROP_TEMPO);
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ int WinMIDIDevice::SetTempo(int tempo)
|
|||
|
||||
int WinMIDIDevice::SetTimeDiv(int timediv)
|
||||
{
|
||||
MIDIPROPTIMEDIV data = { sizeof(MIDIPROPTIMEDIV), timediv };
|
||||
MIDIPROPTIMEDIV data = { sizeof(MIDIPROPTIMEDIV), (DWORD)timediv };
|
||||
return midiStreamProperty(MidiOut, (LPBYTE)&data, MIDIPROP_SET | MIDIPROP_TIMEDIV);
|
||||
}
|
||||
|
||||
|
|
|
@ -108,13 +108,4 @@ inline angle_t absangle(angle_t a)
|
|||
// without additional checking.
|
||||
extern angle_t tantoangle[SLOPERANGE+1];
|
||||
|
||||
inline double bam2rad(angle_t ang)
|
||||
{
|
||||
return double(ang >> 1) * (PI / ANGLE_90);
|
||||
}
|
||||
inline angle_t rad2bam(double ang)
|
||||
{
|
||||
return angle_t(ang * (double(1<<30) / PI)) << 1;
|
||||
}
|
||||
|
||||
#endif // __TABLES_H__
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
* T is the enum type of individual flags,
|
||||
* TT is the underlying integer type used (defaults to DWORD)
|
||||
*/
|
||||
template<typename T, typename TT = DWORD>
|
||||
template<typename T, typename TT = uint32>
|
||||
class TFlags
|
||||
{
|
||||
struct ZeroDummy {};
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "decallib.h"
|
||||
#include "i_system.h"
|
||||
#include "thingdef.h"
|
||||
#include "thingdef_exp.h"
|
||||
#include "r_data/r_translate.h"
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
@ -495,7 +496,8 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
|
|||
else if (def == DEF_Projectile && sc.Compare ("Damage"))
|
||||
{
|
||||
sc.MustGetNumber ();
|
||||
defaults->Damage = CreateDamageFunction(sc.Number);
|
||||
FxDamageValue *x = new FxDamageValue(new FxConstant(sc.Number, sc), false);
|
||||
defaults->Damage = (VMFunction *)(uintptr_t)(ActorDamageFuncs.Push(x) + 1);
|
||||
}
|
||||
else if (def == DEF_Projectile && sc.Compare ("DamageType"))
|
||||
{
|
||||
|
|
|
@ -217,6 +217,39 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, IsPointerEqual)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CountInv
|
||||
//
|
||||
// NON-ACTION function to return the inventory count of an item.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountInv)
|
||||
{
|
||||
if (numret > 0)
|
||||
{
|
||||
assert(ret != NULL);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(self, AActor);
|
||||
PARAM_CLASS(itemtype, AInventory);
|
||||
PARAM_INT_OPT(pick_pointer) { pick_pointer = AAPTR_DEFAULT; }
|
||||
|
||||
self = COPY_AAPTR(self, pick_pointer);
|
||||
if (self == NULL || itemtype == NULL)
|
||||
{
|
||||
ret->SetInt(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
AInventory *item = self->FindInventory(itemtype);
|
||||
ret->SetInt(item ? item->Amount : 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_RearrangePointers
|
||||
|
@ -5553,7 +5586,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem)
|
|||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_INT(speed);
|
||||
PARAM_FIXED(speed);
|
||||
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
|
||||
|
||||
AActor *ref = COPY_AAPTR(self, ptr);
|
||||
|
@ -5573,7 +5606,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
|
|||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatSpeed)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_INT(speed);
|
||||
PARAM_FIXED(speed);
|
||||
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
|
||||
|
||||
AActor *ref = COPY_AAPTR(self, ptr);
|
||||
|
@ -6360,6 +6393,35 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipMax)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_SetChaseThreshold(int threshold, bool def, int ptr)
|
||||
//
|
||||
// Sets the current chase threshold of the actor (pointer). If def is true,
|
||||
// changes the default threshold which the actor resets to once it switches
|
||||
// targets and doesn't have the +QUICKTORETALIATE flag.
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetChaseThreshold)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_INT(threshold);
|
||||
PARAM_BOOL_OPT(def) { def = false; }
|
||||
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
|
||||
|
||||
|
||||
AActor *mobj = COPY_AAPTR(self, ptr);
|
||||
if (!mobj)
|
||||
{
|
||||
ACTION_SET_RESULT(false);
|
||||
return 0;
|
||||
}
|
||||
if (def)
|
||||
mobj->DefThreshold = (threshold >= 0) ? threshold : 0;
|
||||
else
|
||||
mobj->threshold = (threshold >= 0) ? threshold : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_CheckProximity(jump, classname, distance, count, flags, ptr)
|
||||
|
@ -6390,8 +6452,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
|
|||
PARAM_CLASS(classname, AActor);
|
||||
PARAM_FIXED(distance);
|
||||
PARAM_INT_OPT(count) { count = 1; }
|
||||
PARAM_INT(flags) { flags = 0; }
|
||||
PARAM_INT(ptr) { ptr = AAPTR_DEFAULT; }
|
||||
PARAM_INT_OPT(flags) { flags = 0; }
|
||||
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
|
||||
|
||||
ACTION_SET_RESULT(false); //No inventory chain results please.
|
||||
|
||||
|
@ -6426,7 +6488,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
|
|||
//Check inheritance for the classname. Taken partly from CheckClass DECORATE function.
|
||||
if (flags & CPXF_ANCESTOR)
|
||||
{
|
||||
if (!(mo->GetClass()->IsAncestorOf(classname)))
|
||||
if (!(mo->IsKindOf(classname)))
|
||||
continue;
|
||||
}
|
||||
//Otherwise, just check for the regular class name.
|
||||
|
|
|
@ -651,4 +651,6 @@ void InitThingdef()
|
|||
symt.AddSymbol(new PField(NAME_ReactionTime,TypeSInt32, VARF_Native, myoffsetof(AActor,reactiontime)));
|
||||
symt.AddSymbol(new PField(NAME_MeleeRange, TypeFixed, VARF_Native, myoffsetof(AActor,meleerange)));
|
||||
symt.AddSymbol(new PField(NAME_Speed, TypeFixed, VARF_Native, myoffsetof(AActor,Speed)));
|
||||
symt.AddSymbol(new PField(NAME_Threshold, TypeSInt32, VARF_Native, myoffsetof(AActor,threshold)));
|
||||
symt.AddSymbol(new PField(NAME_DefThreshold,TypeSInt32, VARF_Native, myoffsetof(AActor,DefThreshold)));
|
||||
}
|
||||
|
|
|
@ -143,11 +143,13 @@ FxExpression *FxExpression::Resolve(FCompileContext &ctx)
|
|||
|
||||
FxExpression *FxExpression::ResolveAsBoolean(FCompileContext &ctx)
|
||||
{
|
||||
///FIXME: Use an actual boolean type
|
||||
FxExpression *x = Resolve(ctx);
|
||||
if (x != NULL)
|
||||
{
|
||||
switch (x->ValueType.Type)
|
||||
{
|
||||
case VAL_Int:
|
||||
case VAL_Sound:
|
||||
case VAL_Color:
|
||||
case VAL_Name:
|
||||
|
@ -155,6 +157,9 @@ FxExpression *FxExpression::ResolveAsBoolean(FCompileContext &ctx)
|
|||
break;
|
||||
|
||||
default:
|
||||
ScriptPosition.Message(MSG_ERROR, "Not an integral type");
|
||||
delete this;
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1681,7 +1686,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build)
|
|||
op2.Free(build);
|
||||
|
||||
ExpEmit to(build, REGT_INT);
|
||||
build->Emit(OP_EQ_K, 0, op2.RegNum, zero);
|
||||
build->Emit(OP_EQ_K, 1, op2.RegNum, zero);
|
||||
build->Emit(OP_JMP, 2);
|
||||
build->Emit(OP_LI, to.RegNum, 1);
|
||||
build->Emit(OP_JMP, 1);
|
||||
|
@ -1702,7 +1707,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build)
|
|||
op2.Free(build);
|
||||
|
||||
ExpEmit to(build, REGT_INT);
|
||||
build->Emit(OP_EQ_K, 1, op2.RegNum, zero);
|
||||
build->Emit(OP_EQ_K, 0, op2.RegNum, zero);
|
||||
build->Emit(OP_JMP, 2);
|
||||
build->Emit(OP_LI, to.RegNum, 0);
|
||||
build->Emit(OP_JMP, 1);
|
||||
|
@ -2140,7 +2145,6 @@ FxExpression *FxRandomPick::Resolve(FCompileContext &ctx)
|
|||
|
||||
ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
#pragma message("FxRandomPick::Emit: Floating point part needs reviewing!")
|
||||
unsigned i;
|
||||
|
||||
assert(choices.Size() > 0);
|
||||
|
@ -2166,6 +2170,14 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
|||
// automatically pick it as the destination register for each case.
|
||||
resultreg.Free(build);
|
||||
|
||||
// For floating point results, we need to get a new register, since we can't
|
||||
// reuse the integer one used to store the random result.
|
||||
if (ValueType == VAL_Float)
|
||||
{
|
||||
resultreg = ExpEmit(build, REGT_FLOAT);
|
||||
resultreg.Free(build);
|
||||
}
|
||||
|
||||
// Allocate space for the jump table.
|
||||
size_t jumptable = build->Emit(OP_JMP, 0);
|
||||
for (i = 1; i < choices.Size(); ++i)
|
||||
|
@ -2188,8 +2200,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
|||
else
|
||||
{
|
||||
double val = static_cast<FxConstant *>(choices[i])->GetValue().GetFloat();
|
||||
build->Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, build->GetConstantFloat(val));
|
||||
build->ParamChange(-1); // all params should use the same register here.
|
||||
build->Emit(OP_LKF, resultreg.RegNum, build->GetConstantFloat(val));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2200,14 +2211,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
|||
// was expected. Copy it to the one we wanted.
|
||||
|
||||
resultreg.Reuse(build); // This is really just for the assert in Reuse()
|
||||
if (ValueType == VAL_Int)
|
||||
{
|
||||
build->Emit(OP_MOVE, resultreg.RegNum, casereg.RegNum, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_MOVEF, resultreg.RegNum, casereg.RegNum, 0);
|
||||
}
|
||||
build->Emit(ValueType == VAL_Int ? OP_MOVE : OP_MOVEF, resultreg.RegNum, casereg.RegNum, 0);
|
||||
resultreg.Free(build);
|
||||
}
|
||||
// Free this register so the remaining cases can use it.
|
||||
|
|
|
@ -544,6 +544,28 @@ DEFINE_PROPERTY(painthreshold, I, Actor)
|
|||
defaults->PainThreshold = id;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_PROPERTY(defthreshold, I, Actor)
|
||||
{
|
||||
PROP_INT_PARM(id, 0);
|
||||
if (id < 0)
|
||||
I_Error("DefThreshold cannot be negative.");
|
||||
defaults->DefThreshold = id;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_PROPERTY(threshold, I, Actor)
|
||||
{
|
||||
PROP_INT_PARM(id, 0);
|
||||
if (id < 0)
|
||||
I_Error("Threshold cannot be negative.");
|
||||
defaults->threshold = id;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
@ -190,7 +190,7 @@ void SF2Envelope::Release(Voice *v)
|
|||
if (stage == SF2_ATTACK)
|
||||
{
|
||||
// The attack stage does not use an attenuation in cB like all the rest.
|
||||
volume = log10(volume) * -200;
|
||||
volume = float(log10(volume) * -200);
|
||||
}
|
||||
stage = SF2_RELEASE;
|
||||
bUpdating = true;
|
||||
|
|
|
@ -94,7 +94,7 @@ void Renderer::recompute_freq(int v)
|
|||
if (ch->pitchfactor == 0)
|
||||
{
|
||||
/* Damn. Somebody bent the pitch. */
|
||||
ch->pitchfactor = pow(2.f, ((abs(pb) * ch->pitchsens) / (8191.f * 1200.f)));
|
||||
ch->pitchfactor = float(pow(2.f, ((abs(pb) * ch->pitchsens) / (8191.f * 1200.f))));
|
||||
}
|
||||
if (pb < 0)
|
||||
{
|
||||
|
|
|
@ -76,7 +76,7 @@ const char *GetVersionString();
|
|||
|
||||
// Use 4500 as the base git save version, since it's higher than the
|
||||
// SVN revision ever got.
|
||||
#define SAVEVER 4532
|
||||
#define SAVEVER 4533
|
||||
|
||||
#define SAVEVERSTRINGIFY2(x) #x
|
||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||
|
|
|
@ -1487,10 +1487,10 @@ void D3DFB::DoOffByOneCheck ()
|
|||
float texbot = 1.f / float(FBHeight);
|
||||
FBVERTEX verts[4] =
|
||||
{
|
||||
{ -0.5f, -0.5f, 0.5f, 1.f, 0, ~0, 0.f, 0.f },
|
||||
{ 255.5f, -0.5f, 0.5f, 1.f, 0, ~0, texright, 0.f },
|
||||
{ 255.5f, 0.5f, 0.5f, 1.f, 0, ~0, texright, texbot },
|
||||
{ -0.5f, 0.5f, 0.5f, 1.f, 0, ~0, 0.f, texbot }
|
||||
{ -0.5f, -0.5f, 0.5f, 1.f, D3DCOLOR_RGBA(0,0,0,0), D3DCOLOR_RGBA(255,255,255,255), 0.f, 0.f },
|
||||
{ 255.5f, -0.5f, 0.5f, 1.f, D3DCOLOR_RGBA(0,0,0,0), D3DCOLOR_RGBA(255,255,255,255), texright, 0.f },
|
||||
{ 255.5f, 0.5f, 0.5f, 1.f, D3DCOLOR_RGBA(0,0,0,0), D3DCOLOR_RGBA(255,255,255,255), texright, texbot },
|
||||
{ -0.5f, 0.5f, 0.5f, 1.f, D3DCOLOR_RGBA(0,0,0,0), D3DCOLOR_RGBA(255,255,255,255), 0.f, texbot }
|
||||
};
|
||||
int i, c;
|
||||
|
||||
|
|
|
@ -1424,8 +1424,8 @@ static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP
|
|||
ICONINFO iconinfo =
|
||||
{
|
||||
FALSE, // fIcon
|
||||
xhot, // xHotspot
|
||||
yhot, // yHotspot
|
||||
(DWORD)xhot, // xHotspot
|
||||
(DWORD)yhot, // yHotspot
|
||||
and_mask, // hbmMask
|
||||
color_mask // hbmColor
|
||||
};
|
||||
|
|
|
@ -892,7 +892,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); PalEntry x; x.d = param[p].i;
|
||||
#define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); double x = param[p].f;
|
||||
#define PARAM_FIXED_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); fixed_t x = FLOAT2FIXED(param[p].f);
|
||||
#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); angle_t x = angle_t(param[p].f * (ANGLE_90 / 90.0));
|
||||
#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); angle_t x = FLOAT2ANGLE(param[p].f);
|
||||
#define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s();
|
||||
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); FState *x = (FState *)param[p].a;
|
||||
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
|
||||
|
@ -910,7 +910,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_COLOR_OPT_AT(p,x) PalEntry x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x.d = param[p].i; } else
|
||||
#define PARAM_FLOAT_OPT_AT(p,x) double x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = param[p].f; } else
|
||||
#define PARAM_FIXED_OPT_AT(p,x) fixed_t x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = FLOAT2FIXED(param[p].f); } else
|
||||
#define PARAM_ANGLE_OPT_AT(p,x) angle_t x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = angle_t(param[p].f * (ANGLE_90 / 90.0)); } else
|
||||
#define PARAM_ANGLE_OPT_AT(p,x) angle_t x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = FLOAT2ANGLE(param[p].f); } else
|
||||
#define PARAM_STRING_OPT_AT(p,x) FString x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_STRING); x = param[p].s(); } else
|
||||
#define PARAM_STATE_OPT_AT(p,x) FState *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); x = (FState *)param[p].a; } else
|
||||
#define PARAM_POINTER_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER); x = (type *)param[p].a; } else
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <math.h>
|
||||
#include "vm.h"
|
||||
#include "xs_Float.h"
|
||||
|
||||
#define IMPLEMENT_VMEXEC
|
||||
|
||||
|
|
|
@ -339,14 +339,13 @@ begin:
|
|||
OP(SANG):
|
||||
ASSERTA(a); ASSERTF(B); ASSERTKD(C);
|
||||
GETADDR(PA,KC,X_WRITE_NIL);
|
||||
*(VM_UWORD *)ptr = (VM_UWORD)(reg.f[B] * ((1<<30) / 180.0)) << 1; // deg -> BAM
|
||||
*(VM_UWORD *)ptr = (VM_UWORD)(xs_CRoundToInt((reg.f[B]) * (0x40000000/90.))); // deg -> BAM
|
||||
NEXTOP;
|
||||
OP(SANG_R):
|
||||
ASSERTA(a); ASSERTF(B); ASSERTD(C);
|
||||
GETADDR(PA,RC,X_WRITE_NIL);
|
||||
*(VM_UWORD *)ptr = (VM_UWORD)(reg.f[B] * ((1<<30) / 180.0)) << 1;
|
||||
*(VM_UWORD *)ptr = (VM_UWORD)(xs_CRoundToInt((reg.f[B]) * (0x40000000/90.)));
|
||||
NEXTOP;
|
||||
|
||||
OP(SBIT):
|
||||
ASSERTA(a); ASSERTD(B);
|
||||
GETADDR(PA,0,X_WRITE_NIL);
|
||||
|
|
|
@ -1,3 +1,202 @@
|
|||
Version 0.16 (2016-01-21)
|
||||
---------------------------
|
||||
- Fixed bug #127 "code generation error with wide chars and bitmaps (omitted 'goto' statement)"
|
||||
- Added DFA minimization and option '--dfa-minimization <table | moore>'
|
||||
- Fixed bug #128 "very slow DFA construction (resulting in a very large DFA)"
|
||||
- Fixed bug #132 "test failure on big endian archs with 0.15.3"
|
||||
|
||||
Version 0.15.3 (2015-12-02)
|
||||
---------------------------
|
||||
- Fixed bugs and applied patches:
|
||||
#122 "clang does not compile re2c 0.15.x" (reported and fixed by Oleksii Taran).
|
||||
#124 "Get rid of UINT32_MAX and friends" (patch by Sergei Trofimovich, fixes FreeBSD builds).
|
||||
#125 "[OS X] git reports changes not staged for commit in newly cloned repository" (by Oleksii Taran, this fix also applies to Windows).
|
||||
- Added option --no-version that allows to omit version information.
|
||||
- Reduced memory and time consumed with -Wundefined-control-flow.
|
||||
- Improved coverage of input data generated with -S --skeleton.
|
||||
|
||||
Version 0.15.2 (2015-11-23)
|
||||
---------------------------
|
||||
- Fixed build system: lexer depends on bison-generated parser
|
||||
(Gentoo bug: https://bugs.gentoo.org/show_bug.cgi?id=566620)
|
||||
|
||||
Version 0.15.1 (2015-11-22)
|
||||
---------------------------
|
||||
- Fixed test failures caused by locale-sensitive 'sort'.
|
||||
|
||||
Version 0.15 (2015-11-22)
|
||||
-------------------------
|
||||
- Updated website http://re2c.org:
|
||||
added examples
|
||||
updated docs
|
||||
added news
|
||||
added web feed (Atom 1.0)
|
||||
- Added options:
|
||||
-S, --skeleton
|
||||
--empty-class <match-empty | match-none | error>
|
||||
- Added warnings:
|
||||
-W
|
||||
-Werror
|
||||
-W<warning>
|
||||
-Wno-<warning>
|
||||
-Werror-<warning>
|
||||
-Wno-error-<warning>
|
||||
- Added individual warnings:
|
||||
-Wundefined-control-flow
|
||||
-Wunreachable-rules
|
||||
-Wcondition-order
|
||||
-Wuseless-escape
|
||||
-Wempty-character-class
|
||||
-Wswapped-range
|
||||
-Wmatch-empty-string
|
||||
- Fixed options:
|
||||
-- (interpret remaining arguments as non-options)
|
||||
- Deprecated options:
|
||||
-1 --single-pass (single pass is by default now)
|
||||
- Reduced size of the generated .dot files.
|
||||
- Fixed bugs:
|
||||
#27 re2c crashes reading files containing %{ %} (patch by Rui)
|
||||
#51 default rule doesn't work in reuse mode
|
||||
#52 eliminate multiple passes
|
||||
#59 bogus yyaccept in -c mode
|
||||
#60 redundant use of YYMARKER
|
||||
#61 empty character class [] matches empty string
|
||||
#115 flex-style named definitions cause ambiguity in re2c grammar
|
||||
#119 -f with -b/-g generates incorrect dispatch on fill labels
|
||||
#116 empty string with non-empty trailing context consumes code units
|
||||
- Added test options:
|
||||
-j, -j <N> (run tests in N threads, defaults to the number of CPUs)
|
||||
--wine (test windows builds using wine)
|
||||
--skeleton (generate skeleton programs, compile and execute them)
|
||||
--keep-tmp-files (don't delete intermediate files for successful tests)
|
||||
- Updated build system:
|
||||
support out of source builds
|
||||
support `make distcheck`
|
||||
added `make bootstrap` (rebuild re2c after building with precomplied .re files)
|
||||
added `make tests` (run tests with -j)
|
||||
added `make vtests` (run tests with --valgrind -j)
|
||||
added `make wtests` (run tests with --wine -j 1)
|
||||
added Autoconf tests for CXXFLAGS. By default try the following options:
|
||||
-W -Wall -Wextra -Weffc++ -pedantic -Wformat=2 -Wredundant-decls
|
||||
-Wsuggest-attribute=format -Wconversion -Wsign-conversion -O2 -Weverything),
|
||||
respect user-defined CXXFLAGS
|
||||
support Mingw builds: `configure -host i686-w64-mingw32`
|
||||
structured source files
|
||||
removed old MSVC files
|
||||
- Moved development to github (https://github.com/skvadrik/re2c), keep a mirror on sourceforge.
|
||||
|
||||
Version 0.14.3 (2015-05-20)
|
||||
-----------------------------
|
||||
- applied patch '#27 re2c crashes reading files containing %{ %}' by Rui
|
||||
- dropped distfiles for MSVC (they are broken anyway)
|
||||
|
||||
Version 0.14.2 (2015-03-25)
|
||||
-----------------------------
|
||||
- fixed #57 Wrong result only if another rule is present
|
||||
|
||||
Version 0.14.1 (2015-02-27)
|
||||
-----------------------------
|
||||
- fixed #55 re2c-0.14: re2c -V outputs null byte
|
||||
|
||||
Version 0.14 (2015-02-23)
|
||||
-----------------------------
|
||||
- Added generic input API 21 (#21 Support to configure how re2c code interfaced with the symbol buffer?)
|
||||
- fixed #46 re2c generates an infinite loop, depends on existence of previous parser
|
||||
- fixed #47 Dot output label escaped characters
|
||||
|
||||
Version 0.13.7.5 (2014-08-22)
|
||||
-----------------------------
|
||||
- Fixed Gentoo bug: https://bugs.gentoo.org/show_bug.cgi?id=518904 (PHP lexer)
|
||||
|
||||
Version 0.13.7.4 (2014-07-29)
|
||||
-----------------------------
|
||||
- Enabled 'make docs' only if configured with '--enable-docs'
|
||||
- Disallowed to use yacc/byacc instead of bison to build parser
|
||||
- Removed non-portable sed feature in script that runs tests
|
||||
|
||||
Version 0.13.7.3 (2014-07-28)
|
||||
-----------------------------
|
||||
- Fixed CXX warning
|
||||
- Got rid of asciidoc build-time dependency
|
||||
|
||||
Version 0.13.7.2 (2014-07-27)
|
||||
-----------------------------
|
||||
- Included man page into dist, respect users CXXFLAGS.
|
||||
|
||||
Version 0.13.7.1 (2014-07-26)
|
||||
-----------------------------
|
||||
- Added missing files to tarball
|
||||
|
||||
Version 0.13.7 (2014-07-25)
|
||||
---------------------------
|
||||
- Added UTF-8 support
|
||||
- Added UTF-16 support
|
||||
- Added default rule
|
||||
- Added option to control ill-formed Unicode
|
||||
|
||||
Version 0.13.6 (2013-07-04)
|
||||
---------------------------
|
||||
- Fixed #2535084 uint problem with Sun C 5.8
|
||||
- #3308400: allow Yacc-style %{code brackets}%
|
||||
- #2506253: allow C++ // comments
|
||||
- Fixed inplace configuration in -e mode.
|
||||
- Applied #2482572 Typos in error messages.
|
||||
- Applied #2482561 Error in manual section on -r mode.
|
||||
- Fixed #2478216 Wrong start_label in -c mode.
|
||||
- Fixed #2186718 Unescaped backslash in file name of #line directive.
|
||||
- Fixed #2102138 Duplicate case labels on EBCDIC.
|
||||
- Fixed #2088583 Compile problem on AIX.
|
||||
- Fixed #2038610 Ebcdic problem.
|
||||
- improve dot support: make char intervals (e.g. [A-Z]) instead of one edge per char
|
||||
|
||||
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.
|
||||
|
|
|
@ -5,34 +5,99 @@ if( NOT CMAKE_CROSSCOMPILING )
|
|||
include( CheckFunctionExists )
|
||||
include( CheckTypeSize )
|
||||
|
||||
if( MSVC )
|
||||
# Runtime type information is required
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR" )
|
||||
endif()
|
||||
|
||||
set( PACKAGE_NAME re2c )
|
||||
set( PACKAGE_TARNAME re2c )
|
||||
set( PACKAGE_VERSION 0.12.3 )
|
||||
set( PACKAGE_STRING "re2c 0.12.3" )
|
||||
set( PACKAGE_VERSION 0.16 )
|
||||
set( PACKAGE_STRING "re2c 0.16" )
|
||||
set( PACKAGE_BUGREPORT "re2c-general@lists.sourceforge.net" )
|
||||
|
||||
CHECK_FUNCTION_EXISTS( strdup HAVE_STRDUP )
|
||||
CHECK_FUNCTION_EXISTS( strndup HAVE_STRNDUP )
|
||||
|
||||
CHECK_TYPE_SIZE( "0i8" SIZEOF_0I8 )
|
||||
CHECK_TYPE_SIZE( "0l" SIZEOF_0L )
|
||||
CHECK_TYPE_SIZE( "0ll" SIZEOF_0LL )
|
||||
CHECK_TYPE_SIZE( char SIZEOF_CHAR )
|
||||
CHECK_TYPE_SIZE( short SIZEOF_SHORT )
|
||||
CHECK_TYPE_SIZE( int SIZEOF_INT )
|
||||
CHECK_TYPE_SIZE( long SIZEOF_LONG )
|
||||
CHECK_TYPE_SIZE( "long long" SIZEOF_LONG_LONG )
|
||||
CHECK_TYPE_SIZE( "void *" SIZEOF_VOID_P )
|
||||
CHECK_TYPE_SIZE( __int64 SIZEOF___INT_64 )
|
||||
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h )
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
add_definitions( -DHAVE_CONFIG_H )
|
||||
|
||||
file( GLOB SRC_HDR
|
||||
src/codegen/*.h
|
||||
src/conf/*.h
|
||||
src/ir/*.h
|
||||
src/*.h
|
||||
src/parse/*.h
|
||||
src/util/*.h )
|
||||
|
||||
add_executable( re2c
|
||||
actions.cc
|
||||
code.cc
|
||||
dfa.cc
|
||||
main.cc
|
||||
mbo_getopt.cc
|
||||
parser.cc
|
||||
scanner.cc
|
||||
substr.cc
|
||||
translate.cc )
|
||||
${SRC_HDR}
|
||||
src/codegen/bitmap.cc
|
||||
src/codegen/emit_action.cc
|
||||
src/codegen/emit_dfa.cc
|
||||
src/codegen/label.cc
|
||||
src/codegen/go_construct.cc
|
||||
src/codegen/go_destruct.cc
|
||||
src/codegen/go_emit.cc
|
||||
src/codegen/go_used_labels.cc
|
||||
src/codegen/input_api.cc
|
||||
src/codegen/output.cc
|
||||
src/codegen/print.cc
|
||||
src/conf/msg.cc
|
||||
src/conf/opt.cc
|
||||
src/conf/parse_opts.cc
|
||||
src/conf/warn.cc
|
||||
src/ir/nfa/calc_size.cc
|
||||
src/ir/nfa/nfa.cc
|
||||
src/ir/nfa/split.cc
|
||||
src/ir/adfa/adfa.cc
|
||||
src/ir/adfa/prepare.cc
|
||||
src/ir/dfa/determinization.cc
|
||||
src/ir/dfa/fillpoints.cc
|
||||
src/ir/dfa/minimization.cc
|
||||
src/ir/regexp/display.cc
|
||||
src/ir/regexp/encoding/enc.cc
|
||||
src/ir/regexp/encoding/range_suffix.cc
|
||||
src/ir/regexp/encoding/utf8/utf8_regexp.cc
|
||||
src/ir/regexp/encoding/utf8/utf8_range.cc
|
||||
src/ir/regexp/encoding/utf8/utf8.cc
|
||||
src/ir/regexp/encoding/utf16/utf16_regexp.cc
|
||||
src/ir/regexp/encoding/utf16/utf16.cc
|
||||
src/ir/regexp/encoding/utf16/utf16_range.cc
|
||||
src/ir/regexp/fixed_length.cc
|
||||
src/ir/regexp/regexp.cc
|
||||
src/ir/compile.cc
|
||||
src/ir/rule_rank.cc
|
||||
src/ir/skeleton/control_flow.cc
|
||||
src/ir/skeleton/generate_code.cc
|
||||
src/ir/skeleton/generate_data.cc
|
||||
src/ir/skeleton/match_empty.cc
|
||||
src/ir/skeleton/maxlen.cc
|
||||
src/ir/skeleton/skeleton.cc
|
||||
src/ir/skeleton/unreachable.cc
|
||||
src/ir/skeleton/way.cc
|
||||
src/main.cc
|
||||
src/parse/code.cc
|
||||
src/parse/input.cc
|
||||
src/parse/lex.cc
|
||||
src/parse/lex_conf.cc
|
||||
src/parse/parser.cc
|
||||
src/parse/scanner.cc
|
||||
src/parse/unescape.cc
|
||||
src/util/s_to_n32_unsafe.cc
|
||||
src/util/range.cc )
|
||||
|
||||
set( CROSS_EXPORTS ${CROSS_EXPORTS} re2c PARENT_SCOPE )
|
||||
|
||||
|
|
2
tools/re2c/NO_WARRANTY
Normal file
2
tools/re2c/NO_WARRANTY
Normal file
|
@ -0,0 +1,2 @@
|
|||
re2c is distributed with no warranty whatever. The author and any other
|
||||
contributors take no responsibility for the consequences of its use.
|
|
@ -1,188 +1,159 @@
|
|||
re2c Version 0.12.3
|
||||
------------------
|
||||
re2c
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Originally written by Peter Bumbulis (peter@csg.uwaterloo.ca)
|
||||
|
||||
Currently maintained by:
|
||||
Dan Nuffer <nuffer at users.sourceforge.net>
|
||||
Marcus Boerger <helly at users.sourceforge.net>
|
||||
Hartmut Kaiser <hkaiser at users.sourceforge.net>
|
||||
DESCRIPTION
|
||||
--------------------------------------------------------------------------------
|
||||
re2c is a tool for generating C-based recognizers from regular expressions.
|
||||
re2c-based scanners are efficient: for programming languages, given similar
|
||||
specifications, a re2c-based scanner is typically almost twice as fast as a
|
||||
flex-based scanner with little or no increase in size (possibly a decrease
|
||||
on cisc architectures). Indeed, re2c-based scanners are quite competitive with
|
||||
hand-crafted ones.
|
||||
|
||||
Unlike flex, re2c does not generate complete scanners: the user must supply some
|
||||
interface code. While this code is not bulky (about 50-100 lines for a
|
||||
flex-like scanner; see the man page and examples in the distribution) careful
|
||||
coding is required for efficiency (and correctness). One advantage of this
|
||||
arrangement is that the generated code is not tied to any particular input
|
||||
model.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
DOWNLOAD
|
||||
--------------------------------------------------------------------------------
|
||||
The re2c distribution can be found at:
|
||||
https://sourceforge.net/projects/re2c/
|
||||
|
||||
http://sourceforge.net/projects/re2c/
|
||||
Download the latest tarball:
|
||||
https://sourceforge.net/projects/re2c/files/latest/download
|
||||
|
||||
re2c has been developed and tested with the following compilers on various
|
||||
platforms in 32 bit and 64 bit mode:
|
||||
- GCC 3.3 ... 4.1
|
||||
- Microsoft VC 7, 7.1, 8
|
||||
- Intel 9.0
|
||||
- Sun C++ 5.8 (CXXFLAGS='-library=stlport4')
|
||||
- MIPSpro Compilers: Version 7.4.4m
|
||||
Clone git repo:
|
||||
git clone git://git.code.sf.net/p/re2c/code-git
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
GCC 2.x and Microsoft VC 6 are not capable of compiling re2c.
|
||||
|
||||
Building re2c on unix like platforms requires autoconf 2.57 and bison (tested
|
||||
with 1.875 and later). Under windows you don't need autoconf or bison
|
||||
and can use the pregenerated files.
|
||||
BUILD
|
||||
--------------------------------------------------------------------------------
|
||||
Contents:
|
||||
1. simple build
|
||||
2. bootstrap
|
||||
3. out-of-source build
|
||||
4. testing
|
||||
5. rebuild documentation
|
||||
6. build for windows with mingw
|
||||
7. build from git
|
||||
|
||||
You can build this software by simply typing the following commands:
|
||||
./configure
|
||||
make
|
||||
1. Simplest possible build:
|
||||
$ ./configure [--prefix=<prefix>]
|
||||
$ make
|
||||
$ make install
|
||||
This will build re2c and install it (binary and man page) to <prefix> (defaults
|
||||
to /usr/local).
|
||||
|
||||
The above version will be based on the pregenerated scanner.cc file.
|
||||
If you want to build that file yourself (recommended when installing
|
||||
re2c) you need the following steps:
|
||||
./configure
|
||||
make
|
||||
rm -f scanner.cc
|
||||
make install
|
||||
2. Bootstrap and rebuild:
|
||||
$ ./configure [--prefix=<prefix>]
|
||||
$ make bootstrap
|
||||
$ make install
|
||||
Usual bootstrap procedure: re2c uses re2c to compile its lexer.
|
||||
1. build lexer (if make finds re2c binary in build directory, it will build lexer
|
||||
from source, otherwize it will use prebuilt lexer)
|
||||
2. build re2c
|
||||
3. build lexer from source using re2c binary in build directory
|
||||
4. rebuild re2c
|
||||
|
||||
Or you can create a rpm package and install it by the following commands:
|
||||
./configure
|
||||
make rpm
|
||||
rpm -Uhv <packagedir>/re2c-0.12.3-1.rpm
|
||||
3. Out-of-source build:
|
||||
$ mkdir <build-directory>
|
||||
$ cd <build-directory>
|
||||
$ <path-to-configure>/configure [--prefix=<prefix>]
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
If you want to build from CVS then the first thing you should do is
|
||||
regenerating all build files using the following command:
|
||||
./autogen.sh
|
||||
and then continue with one of the above described build methods. Or if you
|
||||
need to generate RPM packages for cvs builds use these commands:
|
||||
./autogen.sh
|
||||
./configure
|
||||
./makerpm <release>
|
||||
rpm -Uhv <packagedir>/re2c-0.12.3-<release>.rpm
|
||||
4. Testing:
|
||||
$ make check
|
||||
This will redirect test script output to file. If you want to see progress:
|
||||
$ make tests
|
||||
Testing under valgrind (takes a long time):
|
||||
$ make vtests
|
||||
|
||||
Here <realease> should be a number like 1. And <packagedir> must equal
|
||||
the directory where the makerpm step has written the generated rpm to.
|
||||
5. Rebuild documentation (requires rst2man.py):
|
||||
$ ./configure --enable-docs [--prefix=<prefix>]
|
||||
$ make docs
|
||||
$ make install
|
||||
|
||||
If you are on a debian system you can use the tool 'alien' to convert rpms
|
||||
to debian packages.
|
||||
6. Build for windows using mingw:
|
||||
$ ../configure --host i686-w64-mingw32 [--prefix=<prefix>]
|
||||
$ make
|
||||
This will result into an executable re2c.exe, which can be tested with wine:
|
||||
$ make wtests
|
||||
|
||||
When building with native SUN compilers you need to set the following compiler
|
||||
flags: CXXFLAGS='-g -compat5 -library=stlport4'.
|
||||
7. If you want to build from git, you'll first need to generate autotools files:
|
||||
$ ./autogen.sh
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
If you want to build re2c on a windows system you can either use cygwin and one
|
||||
of the methods described above or use Microsoft Visual C .NET 2002 or later
|
||||
with the solution files provided (re2c.sln for 2002/2003 and re2c-2005.sln for
|
||||
version 2005). re2c cannot be built with Microsoft Visual C 6.0 or earlier.
|
||||
|
||||
re2c is a great tool for writing fast and flexible lexers. It has
|
||||
served many people well for many years. re2c is on the order of 2-3
|
||||
times faster than a flex based scanner, and its input model is much
|
||||
more flexible.
|
||||
INFO
|
||||
--------------------------------------------------------------------------------
|
||||
$ man re2c
|
||||
|
||||
For an introduction to re2c refer to the lessons sub directory.
|
||||
re2c home page:
|
||||
re2c.org
|
||||
|
||||
Peter's original version 0.5 ANNOUNCE and README follows.
|
||||
re2c manual:
|
||||
re2c.org/manual.html
|
||||
|
||||
--
|
||||
Ulya Trofimovich's blog on re2c:
|
||||
skvadrik.github.io/aleph_null/re2c.html
|
||||
|
||||
re2c is a tool for generating C-based recognizers from regular
|
||||
expressions. re2c-based scanners are efficient: for programming
|
||||
languages, given similar specifications, an re2c-based scanner is
|
||||
typically almost twice as fast as a flex-based scanner with little or no
|
||||
increase in size (possibly a decrease on cisc architectures). Indeed,
|
||||
re2c-based scanners are quite competitive with hand-crafted ones.
|
||||
Original paper on re2c: "RE2C: a More Versatile Parser Generator" (1994, Peter
|
||||
Bumbulis and Donald D. Cowan).
|
||||
|
||||
Unlike flex, re2c does not generate complete scanners: the user must
|
||||
supply some interface code. While this code is not bulky (about 50-100
|
||||
lines for a flex-like scanner; see the man page and examples in the
|
||||
distribution) careful coding is required for efficiency (and
|
||||
correctness). One advantage of this arrangement is that the generated
|
||||
code is not tied to any particular input model. For example, re2c
|
||||
generated code can be used to scan data from a null-byte terminated
|
||||
buffer as illustrated below.
|
||||
Examples can be found in 'examples' directory.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Given the following source
|
||||
|
||||
#define NULL ((char*) 0)
|
||||
char *scan(char *p)
|
||||
{
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT p
|
||||
#define YYFILL(n)
|
||||
/*!re2c
|
||||
[0-9]+ {return YYCURSOR;}
|
||||
[\000-\377] {return NULL;}
|
||||
*/
|
||||
}
|
||||
MAILING LISTS
|
||||
--------------------------------------------------------------------------------
|
||||
re2c-general:
|
||||
re2c-general@lists.sourceforge.net
|
||||
re2c-devel:
|
||||
re2c-devel@lists.sourceforge.net
|
||||
|
||||
re2c will generate
|
||||
You are welcome to ask for help or share your thoughts and ideas about re2c :)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
/* Generated by re2c on Sat Apr 16 11:40:58 1994 */
|
||||
#line 1 "simple.re"
|
||||
#define NULL ((char*) 0)
|
||||
char *scan(char *p)
|
||||
{
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT p
|
||||
#define YYFILL(n)
|
||||
{
|
||||
YYCTYPE yych;
|
||||
unsigned int yyaccept;
|
||||
|
||||
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if(yych <= '/') goto yy4;
|
||||
if(yych >= ':') goto yy4;
|
||||
yy2: yych = *++YYCURSOR;
|
||||
goto yy7;
|
||||
yy3:
|
||||
#line 9
|
||||
{return YYCURSOR;}
|
||||
yy4: yych = *++YYCURSOR;
|
||||
yy5:
|
||||
#line 10
|
||||
{return NULL;}
|
||||
yy6: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy7: if(yych <= '/') goto yy3;
|
||||
if(yych <= '9') goto yy6;
|
||||
goto yy3;
|
||||
}
|
||||
#line 11
|
||||
BUGS
|
||||
--------------------------------------------------------------------------------
|
||||
Please report any bugs and send feature requests to:
|
||||
https://sourceforge.net/p/re2c/_list/tickets
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
Note that most compilers will perform dead-code elimination to remove
|
||||
all YYCURSOR, YYLIMIT comparisions.
|
||||
AUTHORS
|
||||
--------------------------------------------------------------------------------
|
||||
Originally written by Peter Bumbulis (peter@csg.uwaterloo.ca)
|
||||
Currently maintained by:
|
||||
Ulya Trofimovich <skvadrik@gmail.com>
|
||||
Dan Nuffer <nuffer@users.sourceforge.net>
|
||||
Marcus Boerger <helly@users.sourceforge.net>
|
||||
Hartmut Kaiser <hkaiser@users.sourceforge.net>
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
re2c was developed for a particular project (constructing a fast REXX
|
||||
scanner of all things!) and so while it has some rough edges, it should
|
||||
be quite usable. More information about re2c can be found in the
|
||||
(admittedly skimpy) man page; the algorithms and heuristics used are
|
||||
described in an upcoming LOPLAS article (included in the distribution).
|
||||
Probably the best way to find out more about re2c is to try the supplied
|
||||
examples. re2c is written in C++, and is currently being developed
|
||||
under Linux using gcc 2.5.8.
|
||||
|
||||
Peter
|
||||
LICENSE
|
||||
--------------------------------------------------------------------------------
|
||||
re2c is distributed with no warranty whatever. The code is certain to contain
|
||||
errors. Neither the author nor any contributor takes responsibility for any
|
||||
consequences of its use.
|
||||
|
||||
--
|
||||
|
||||
re2c is distributed with no warranty whatever. The code is certain to
|
||||
contain errors. Neither the author nor any contributor takes
|
||||
responsibility for any consequences of its use.
|
||||
|
||||
re2c is in the public domain. The data structures and algorithms used
|
||||
in re2c are all either taken from documents available to the general
|
||||
public or are inventions of the author. Programs generated by re2c may
|
||||
be distributed freely. re2c itself may be distributed freely, in source
|
||||
or binary, unchanged or modified. Distributors may charge whatever fees
|
||||
they can obtain for re2c.
|
||||
re2c is in the public domain. The data structures and algorithms used in re2c
|
||||
are all either taken from documents available to the general public or are
|
||||
inventions of the authors. Programs generated by re2c may be distributed freely.
|
||||
re2c itself may be distributed freely, in source or binary, unchanged or
|
||||
modified. Distributors may charge whatever fees they can obtain for re2c.
|
||||
|
||||
If you do make use of re2c, or incorporate it into a larger project an
|
||||
acknowledgement somewhere (documentation, research report, etc.) would
|
||||
be appreciated.
|
||||
|
||||
Please send bug reports and feedback (including suggestions for
|
||||
improving the distribution) to
|
||||
|
||||
peter@csg.uwaterloo.ca
|
||||
|
||||
Include a small example and the banner from parser.y with bug reports.
|
||||
|
||||
acknowledgement somewhere (documentation, research report, etc.) would be
|
||||
appreciated.
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,57 +0,0 @@
|
|||
/* $Id: basics.h 520 2006-05-25 13:31:06Z helly $ */
|
||||
#ifndef _basics_h
|
||||
#define _basics_h
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "config_w32.h"
|
||||
#endif
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
#if SIZEOF_CHAR == 1
|
||||
typedef unsigned char byte;
|
||||
#elif SIZEOF_SHORT == 1
|
||||
typedef unsigned short byte;
|
||||
#elif SIZEOF_INT == 1
|
||||
typedef unsigned int byte;
|
||||
#elif SIZEOF_LONG == 1
|
||||
typedef unsigned long byte;
|
||||
#else
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_CHAR == 2
|
||||
typedef unsigned char word;
|
||||
#elif SIZEOF_SHORT == 2
|
||||
typedef unsigned short word;
|
||||
#elif SIZEOF_INT == 2
|
||||
typedef unsigned int word;
|
||||
#elif SIZEOF_LONG == 2
|
||||
typedef unsigned long word;
|
||||
#else
|
||||
typedef unsigned short word;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_CHAR == 4
|
||||
typedef unsigned char dword;
|
||||
#elif SIZEOF_SHORT == 4
|
||||
typedef unsigned short dword;
|
||||
#elif SIZEOF_INT == 4
|
||||
typedef unsigned int dword;
|
||||
#elif SIZEOF_LONG == 4
|
||||
typedef unsigned long dword;
|
||||
#else
|
||||
typedef unsigned long dword;
|
||||
#endif
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned long ulong;
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
#endif
|
1806
tools/re2c/code.cc
1806
tools/re2c/code.cc
File diff suppressed because it is too large
Load diff
|
@ -1,53 +0,0 @@
|
|||
/* $Id: code.h 525 2006-05-25 13:32:49Z helly $ */
|
||||
#ifndef _code_h
|
||||
#define _code_h
|
||||
|
||||
#include "re.h"
|
||||
#include "dfa.h"
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
class BitMap
|
||||
{
|
||||
public:
|
||||
static BitMap *first;
|
||||
|
||||
const Go *go;
|
||||
const State *on;
|
||||
const BitMap *next;
|
||||
uint i;
|
||||
uint m;
|
||||
|
||||
public:
|
||||
static const BitMap *find(const Go*, const State*);
|
||||
static const BitMap *find(const State*);
|
||||
static void gen(std::ostream&, uint ind, uint, uint);
|
||||
static void stats();
|
||||
BitMap(const Go*, const State*);
|
||||
~BitMap();
|
||||
|
||||
#if PEDANTIC
|
||||
BitMap(const BitMap& oth)
|
||||
: go(oth.go)
|
||||
, on(oth.on)
|
||||
, next(oth.next)
|
||||
, i(oth.i)
|
||||
, m(oth.m)
|
||||
{
|
||||
}
|
||||
BitMap& operator = (const BitMap& oth)
|
||||
{
|
||||
new(this) BitMap(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable: 4355) /* 'this' : used in base member initializer list */
|
||||
#endif
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||
/* $Id: token.h 547 2006-05-25 13:40:35Z helly $ */
|
||||
#ifndef _code_names_h
|
||||
#define _code_names_h
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
class CodeNames: public std::map<std::string, std::string>
|
||||
{
|
||||
public:
|
||||
std::string& operator [] (const char * what);
|
||||
};
|
||||
|
||||
inline std::string& CodeNames::operator [] (const char * what)
|
||||
{
|
||||
CodeNames::iterator it = find(std::string(what));
|
||||
|
||||
if (it != end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return insert(std::make_pair(std::string(what), std::string(what))).first->second;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
#endif
|
|
@ -1,10 +1,7 @@
|
|||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#cmakedefine HAVE_STRDUP
|
||||
|
||||
/* Define to 1 if you have the `strndup' function. */
|
||||
#cmakedefine HAVE_STRNDUP
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@
|
||||
|
||||
/* Name of package */
|
||||
#cmakedefine PACKAGE "@PACKAGE_NAME@"
|
||||
|
@ -21,21 +18,41 @@
|
|||
/* Define to the one symbol short name of this package. */
|
||||
#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#cmakedefine PACKAGE_URL "@PACKAGE_URL@"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
/* The size of `0i8', as computed by sizeof. */
|
||||
#cmakedefine SIZEOF_0I8 @SIZEOF_0I8@
|
||||
|
||||
/* The size of `0l', as computed by sizeof. */
|
||||
#cmakedefine SIZEOF_0L @SIZEOF_0L@
|
||||
|
||||
/* The size of `0ll', as computed by sizeof. */
|
||||
#cmakedefine SIZEOF_0LL @SIZEOF_0LL@
|
||||
|
||||
/* The size of `char', as computed by sizeof. */
|
||||
#define SIZEOF_CHAR @SIZEOF_CHAR@
|
||||
#cmakedefine SIZEOF_CHAR @SIZEOF_CHAR@
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#define SIZEOF_INT @SIZEOF_INT@
|
||||
#cmakedefine SIZEOF_INT @SIZEOF_INT@
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG @SIZEOF_LONG@
|
||||
#cmakedefine SIZEOF_LONG @SIZEOF_LONG@
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#cmakedefine SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#define SIZEOF_SHORT @SIZEOF_SHORT@
|
||||
#cmakedefine SIZEOF_SHORT @SIZEOF_SHORT@
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#cmakedefine SIZEOF_VOID_P @SIZEOF_VOID_P@
|
||||
|
||||
/* The size of `__int64', as computed by sizeof. */
|
||||
#cmakedefine SIZEOF___INT64 @SIZEOF___INT64@
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
#cmakedefine VERSION @PACKAGE_VERSION@
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
/* config.h. Generated by configure. */
|
||||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#define HAVE_GETPAGESIZE 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have a working `mmap' system call. */
|
||||
/* #undef HAVE_MMAP */
|
||||
|
||||
/* Define to 1 if you have the `munmap' function. */
|
||||
#define HAVE_MUNMAP 1
|
||||
|
||||
/* Define to 1 if stdbool.h conforms to C99. */
|
||||
#define HAVE_STDBOOL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#define HAVE_STRDUP 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if the system has the type `_Bool'. */
|
||||
#define HAVE__BOOL 1
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "re2c"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "re2c-general@lists.sourceforge.net"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "re2c"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "re2c 0.12.3"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "re2c"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.12.3"
|
||||
|
||||
/* The size of a `char', as computed by sizeof. */
|
||||
#define SIZEOF_CHAR 1
|
||||
|
||||
/* The size of a `int', as computed by sizeof. */
|
||||
#define SIZEOF_INT 4
|
||||
|
||||
/* The size of a `long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG 4
|
||||
|
||||
/* The size of a `short', as computed by sizeof. */
|
||||
#define SIZEOF_SHORT 2
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.12.3"
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define to empty if the keyword `volatile' does not work. Warning: valid
|
||||
code using `volatile' can become incorrect without. Disable with care. */
|
||||
/* #undef volatile */
|
|
@ -1,416 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "globals.h"
|
||||
#include "substr.h"
|
||||
#include "dfa.h"
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
void prtChOrHex(std::ostream& o, uint c, bool useTalx)
|
||||
{
|
||||
int oc = (int)(re2c::wFlag || !useTalx ? c : re2c::talx[c]);
|
||||
|
||||
if ((oc < 256) && isprint(oc))
|
||||
{
|
||||
o << '\'';
|
||||
prtCh(o, c);
|
||||
o << '\'';
|
||||
}
|
||||
else
|
||||
{
|
||||
prtHex(o, c);
|
||||
}
|
||||
}
|
||||
|
||||
void prtHex(std::ostream& o, uint c, bool useTalx)
|
||||
{
|
||||
int oc = (int)(re2c::wFlag || !useTalx ? c : re2c::talx[c]);
|
||||
|
||||
if (re2c::uFlag)
|
||||
{
|
||||
o << "0x"
|
||||
<< hexCh(oc >> 28)
|
||||
<< hexCh(oc >> 24)
|
||||
<< hexCh(oc >> 20)
|
||||
<< hexCh(oc >> 16)
|
||||
<< hexCh(oc >> 12)
|
||||
<< hexCh(oc >> 8)
|
||||
<< hexCh(oc >> 4)
|
||||
<< hexCh(oc);
|
||||
}
|
||||
else if (re2c::wFlag)
|
||||
{
|
||||
o << "0x"
|
||||
<< hexCh(oc >> 12)
|
||||
<< hexCh(oc >> 8)
|
||||
<< hexCh(oc >> 4)
|
||||
<< hexCh(oc);
|
||||
}
|
||||
else
|
||||
{
|
||||
o << "0x"
|
||||
<< hexCh(oc >> 4)
|
||||
<< hexCh(oc);
|
||||
}
|
||||
}
|
||||
|
||||
void prtCh(std::ostream& o, uint c, bool useTalx)
|
||||
{
|
||||
int oc = (int)(re2c::wFlag || !useTalx ? c : re2c::talx[c]);
|
||||
|
||||
switch (oc)
|
||||
{
|
||||
case '\'':
|
||||
o << "\\'";
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
o << "\\n";
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
o << "\\t";
|
||||
break;
|
||||
|
||||
case '\v':
|
||||
o << "\\v";
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
o << "\\b";
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
o << "\\r";
|
||||
break;
|
||||
|
||||
case '\f':
|
||||
o << "\\f";
|
||||
break;
|
||||
|
||||
case '\a':
|
||||
o << "\\a";
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
o << "\\\\";
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if ((oc < 256) && isprint(oc))
|
||||
{
|
||||
o << (char) oc;
|
||||
}
|
||||
else if (re2c::uFlag)
|
||||
{
|
||||
o << "0x"
|
||||
<< hexCh(oc >> 20)
|
||||
<< hexCh(oc >> 16)
|
||||
<< hexCh(oc >> 12)
|
||||
<< hexCh(oc >> 8)
|
||||
<< hexCh(oc >> 4)
|
||||
<< hexCh(oc);
|
||||
}
|
||||
else if (re2c::wFlag)
|
||||
{
|
||||
o << "0x"
|
||||
<< hexCh(oc >> 12)
|
||||
<< hexCh(oc >> 8)
|
||||
<< hexCh(oc >> 4)
|
||||
<< hexCh(oc);
|
||||
}
|
||||
else
|
||||
{
|
||||
o << '\\' << octCh(oc / 64) << octCh(oc / 8) << octCh(oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printSpan(std::ostream& o, uint lb, uint ub)
|
||||
{
|
||||
if (lb > ub)
|
||||
{
|
||||
o << "*";
|
||||
}
|
||||
|
||||
o << "[";
|
||||
|
||||
if ((ub - lb) == 1)
|
||||
{
|
||||
prtCh(o, lb);
|
||||
}
|
||||
else
|
||||
{
|
||||
prtCh(o, lb);
|
||||
o << "-";
|
||||
prtCh(o, ub - 1);
|
||||
}
|
||||
|
||||
o << "]";
|
||||
}
|
||||
|
||||
uint Span::show(std::ostream &o, uint lb) const
|
||||
{
|
||||
if (to)
|
||||
{
|
||||
printSpan(o, lb, ub);
|
||||
o << " " << to->label << "; ";
|
||||
}
|
||||
|
||||
return ub;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &o, const State &s)
|
||||
{
|
||||
o << "state " << s.label;
|
||||
|
||||
if (s.rule)
|
||||
{
|
||||
o << " accepts " << s.rule->accept;
|
||||
}
|
||||
|
||||
o << "\n";
|
||||
|
||||
uint lb = 0;
|
||||
|
||||
for (uint i = 0; i < s.go.nSpans; ++i)
|
||||
{
|
||||
lb = s.go.span[i].show(o, lb);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &o, const DFA &dfa)
|
||||
{
|
||||
for (State *s = dfa.head; s; s = s->next)
|
||||
{
|
||||
o << s << "\n\n";
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
State::State()
|
||||
: label(0)
|
||||
, rule(NULL)
|
||||
, next(0)
|
||||
, link(NULL)
|
||||
, depth(0)
|
||||
, kCount(0)
|
||||
, kernel(NULL)
|
||||
, isPreCtxt(false)
|
||||
, isBase(false)
|
||||
, go()
|
||||
, action(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
State::~State()
|
||||
{
|
||||
delete action;
|
||||
delete [] kernel;
|
||||
delete [] go.span;
|
||||
}
|
||||
|
||||
static Ins **closure(Ins **cP, Ins *i)
|
||||
{
|
||||
while (!isMarked(i))
|
||||
{
|
||||
mark(i);
|
||||
*(cP++) = i;
|
||||
|
||||
if (i->i.tag == FORK)
|
||||
{
|
||||
cP = closure(cP, i + 1);
|
||||
i = (Ins*) i->i.link;
|
||||
}
|
||||
else if (i->i.tag == GOTO || i->i.tag == CTXT)
|
||||
{
|
||||
i = (Ins*) i->i.link;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return cP;
|
||||
}
|
||||
|
||||
struct GoTo
|
||||
{
|
||||
Char ch;
|
||||
void *to;
|
||||
};
|
||||
|
||||
DFA::DFA(Ins *ins, uint ni, uint lb, uint ub, Char *rep)
|
||||
: lbChar(lb)
|
||||
, ubChar(ub)
|
||||
, nStates(0)
|
||||
, head(NULL)
|
||||
, tail(&head)
|
||||
, toDo(NULL)
|
||||
{
|
||||
Ins **work = new Ins * [ni + 1];
|
||||
uint nc = ub - lb;
|
||||
GoTo *goTo = new GoTo[nc];
|
||||
Span *span = new Span[nc];
|
||||
memset((char*) goTo, 0, nc*sizeof(GoTo));
|
||||
findState(work, closure(work, &ins[0]) - work);
|
||||
|
||||
while (toDo)
|
||||
{
|
||||
State *s = toDo;
|
||||
toDo = s->link;
|
||||
|
||||
Ins **cP, **iP, *i;
|
||||
uint nGoTos = 0;
|
||||
uint j;
|
||||
|
||||
s->rule = NULL;
|
||||
|
||||
for (iP = s->kernel; (i = *iP); ++iP)
|
||||
{
|
||||
if (i->i.tag == CHAR)
|
||||
{
|
||||
for (Ins *j = i + 1; j < (Ins*) i->i.link; ++j)
|
||||
{
|
||||
if (!(j->c.link = goTo[j->c.value - lb].to))
|
||||
goTo[nGoTos++].ch = j->c.value;
|
||||
|
||||
goTo[j->c.value - lb].to = j;
|
||||
}
|
||||
}
|
||||
else if (i->i.tag == TERM)
|
||||
{
|
||||
if (!s->rule || ((RuleOp*) i->i.link)->accept < s->rule->accept)
|
||||
s->rule = (RuleOp*) i->i.link;
|
||||
}
|
||||
else if (i->i.tag == CTXT)
|
||||
{
|
||||
s->isPreCtxt = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < nGoTos; ++j)
|
||||
{
|
||||
GoTo *go = &goTo[goTo[j].ch - lb];
|
||||
i = (Ins*) go->to;
|
||||
|
||||
for (cP = work; i; i = (Ins*) i->c.link)
|
||||
cP = closure(cP, i + i->c.bump);
|
||||
|
||||
go->to = findState(work, cP - work);
|
||||
}
|
||||
|
||||
s->go.nSpans = 0;
|
||||
|
||||
for (j = 0; j < nc;)
|
||||
{
|
||||
State *to = (State*) goTo[rep[j]].to;
|
||||
|
||||
while (++j < nc && goTo[rep[j]].to == to) ;
|
||||
|
||||
span[s->go.nSpans].ub = lb + j;
|
||||
|
||||
span[s->go.nSpans].to = to;
|
||||
|
||||
s->go.nSpans++;
|
||||
}
|
||||
|
||||
for (j = nGoTos; j-- > 0;)
|
||||
goTo[goTo[j].ch - lb].to = NULL;
|
||||
|
||||
s->go.span = new Span[s->go.nSpans];
|
||||
|
||||
memcpy((char*) s->go.span, (char*) span, s->go.nSpans*sizeof(Span));
|
||||
|
||||
(void) new Match(s);
|
||||
|
||||
}
|
||||
|
||||
delete [] work;
|
||||
delete [] goTo;
|
||||
delete [] span;
|
||||
}
|
||||
|
||||
DFA::~DFA()
|
||||
{
|
||||
State *s;
|
||||
|
||||
while ((s = head))
|
||||
{
|
||||
head = s->next;
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
void DFA::addState(State **a, State *s)
|
||||
{
|
||||
s->label = nStates++;
|
||||
s->next = *a;
|
||||
*a = s;
|
||||
|
||||
if (a == tail)
|
||||
tail = &s->next;
|
||||
}
|
||||
|
||||
State *DFA::findState(Ins **kernel, uint kCount)
|
||||
{
|
||||
Ins **cP, **iP, *i;
|
||||
State *s;
|
||||
|
||||
kernel[kCount] = NULL;
|
||||
|
||||
cP = kernel;
|
||||
|
||||
for (iP = kernel; (i = *iP); ++iP)
|
||||
{
|
||||
if (i->i.tag == CHAR || i->i.tag == TERM || i->i.tag == CTXT)
|
||||
{
|
||||
*cP++ = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
unmark(i);
|
||||
}
|
||||
}
|
||||
|
||||
kCount = cP - kernel;
|
||||
kernel[kCount] = NULL;
|
||||
|
||||
for (s = head; s; s = s->next)
|
||||
{
|
||||
if (s->kCount == kCount)
|
||||
{
|
||||
for (iP = s->kernel; (i = *iP); ++iP)
|
||||
if (!isMarked(i))
|
||||
goto nextState;
|
||||
|
||||
goto unmarkAll;
|
||||
}
|
||||
|
||||
nextState:
|
||||
;
|
||||
}
|
||||
|
||||
s = new State;
|
||||
addState(tail, s);
|
||||
s->kCount = kCount;
|
||||
s->kernel = new Ins * [kCount + 1];
|
||||
memcpy(s->kernel, kernel, (kCount + 1)*sizeof(Ins*));
|
||||
s->link = toDo;
|
||||
toDo = s;
|
||||
|
||||
unmarkAll:
|
||||
|
||||
for (iP = kernel; (i = *iP); ++iP)
|
||||
unmark(i);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
} // end namespace re2c
|
||||
|
366
tools/re2c/dfa.h
366
tools/re2c/dfa.h
|
@ -1,366 +0,0 @@
|
|||
/* $Id: dfa.h 569 2006-06-05 22:14:00Z helly $ */
|
||||
#ifndef _dfa_h
|
||||
#define _dfa_h
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include "re.h"
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
extern void prtCh(std::ostream&, uint, bool useTalx = true);
|
||||
extern void prtHex(std::ostream&, uint, bool useTalx = true);
|
||||
extern void prtChOrHex(std::ostream&, uint, bool useTalx = true);
|
||||
extern void printSpan(std::ostream&, uint, uint);
|
||||
|
||||
class DFA;
|
||||
|
||||
class State;
|
||||
|
||||
class Action
|
||||
{
|
||||
|
||||
public:
|
||||
State *state;
|
||||
|
||||
public:
|
||||
Action(State*);
|
||||
virtual ~Action();
|
||||
|
||||
virtual void emit(std::ostream&, uint, bool&) const = 0;
|
||||
virtual bool isRule() const;
|
||||
virtual bool isMatch() const;
|
||||
virtual bool isInitial() const;
|
||||
virtual bool readAhead() const;
|
||||
|
||||
#ifdef PEDANTIC
|
||||
protected:
|
||||
Action(const Action& oth)
|
||||
: state(oth.state)
|
||||
{
|
||||
}
|
||||
Action& operator = (const Action& oth)
|
||||
{
|
||||
state = oth.state;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class Match: public Action
|
||||
{
|
||||
public:
|
||||
Match(State*);
|
||||
void emit(std::ostream&, uint, bool&) const;
|
||||
bool isMatch() const;
|
||||
};
|
||||
|
||||
class Enter: public Action
|
||||
{
|
||||
public:
|
||||
uint label;
|
||||
|
||||
public:
|
||||
Enter(State*, uint);
|
||||
void emit(std::ostream&, uint, bool&) const;
|
||||
};
|
||||
|
||||
class Initial: public Enter
|
||||
{
|
||||
public:
|
||||
bool setMarker;
|
||||
|
||||
public:
|
||||
Initial(State*, uint, bool);
|
||||
void emit(std::ostream&, uint, bool&) const;
|
||||
bool isInitial() const;
|
||||
};
|
||||
|
||||
class Save: public Match
|
||||
{
|
||||
|
||||
public:
|
||||
uint selector;
|
||||
|
||||
public:
|
||||
Save(State*, uint);
|
||||
void emit(std::ostream&, uint, bool&) const;
|
||||
bool isMatch() const;
|
||||
};
|
||||
|
||||
class Move: public Action
|
||||
{
|
||||
|
||||
public:
|
||||
Move(State*);
|
||||
void emit(std::ostream&, uint, bool&) const;
|
||||
};
|
||||
|
||||
class Accept: public Action
|
||||
{
|
||||
|
||||
public:
|
||||
typedef std::map<uint, State*> RuleMap;
|
||||
|
||||
uint nRules;
|
||||
uint *saves;
|
||||
State **rules;
|
||||
RuleMap mapRules;
|
||||
|
||||
public:
|
||||
Accept(State*, uint, uint*, State**);
|
||||
void emit(std::ostream&, uint, bool&) const;
|
||||
void emitBinary(std::ostream &o, uint ind, uint l, uint r, bool &readCh) const;
|
||||
void genRuleMap();
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
Accept(const Accept& oth)
|
||||
: Action(oth)
|
||||
, nRules(oth.nRules)
|
||||
, saves(oth.saves)
|
||||
, rules(oth.rules)
|
||||
{
|
||||
}
|
||||
Accept& operator=(const Accept& oth)
|
||||
{
|
||||
new(this) Accept(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class Rule: public Action
|
||||
{
|
||||
|
||||
public:
|
||||
RuleOp *rule;
|
||||
|
||||
public:
|
||||
Rule(State*, RuleOp*);
|
||||
void emit(std::ostream&, uint, bool&) const;
|
||||
bool isRule() const;
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
Rule (const Rule& oth)
|
||||
: Action(oth)
|
||||
, rule(oth.rule)
|
||||
{
|
||||
}
|
||||
Rule& operator=(const Rule& oth)
|
||||
{
|
||||
new(this) Rule(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class Span
|
||||
{
|
||||
|
||||
public:
|
||||
uint ub;
|
||||
State *to;
|
||||
|
||||
public:
|
||||
uint show(std::ostream&, uint) const;
|
||||
};
|
||||
|
||||
class Go
|
||||
{
|
||||
public:
|
||||
Go()
|
||||
: nSpans(0)
|
||||
, wSpans(~0u)
|
||||
, lSpans(~0u)
|
||||
, dSpans(~0u)
|
||||
, lTargets(~0u)
|
||||
, span(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
uint nSpans; // number of spans
|
||||
uint wSpans; // number of spans in wide mode
|
||||
uint lSpans; // number of low (non wide) spans
|
||||
uint dSpans; // number of decision spans (decide between g and b mode)
|
||||
uint lTargets;
|
||||
Span *span;
|
||||
|
||||
public:
|
||||
void genGoto( std::ostream&, uint ind, const State *from, const State *next, bool &readCh);
|
||||
void genBase( std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
|
||||
void genLinear(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
|
||||
void genBinary(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
|
||||
void genSwitch(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
|
||||
void genCpGoto(std::ostream&, uint ind, const State *from, const State *next, bool &readCh) const;
|
||||
void compact();
|
||||
void unmap(Go*, const State*);
|
||||
};
|
||||
|
||||
class State
|
||||
{
|
||||
|
||||
public:
|
||||
uint label;
|
||||
RuleOp *rule;
|
||||
State *next;
|
||||
State *link;
|
||||
uint depth; // for finding SCCs
|
||||
uint kCount;
|
||||
Ins **kernel;
|
||||
|
||||
bool isPreCtxt;
|
||||
bool isBase;
|
||||
Go go;
|
||||
Action *action;
|
||||
|
||||
public:
|
||||
State();
|
||||
~State();
|
||||
void emit(std::ostream&, uint, bool&) const;
|
||||
friend std::ostream& operator<<(std::ostream&, const State&);
|
||||
friend std::ostream& operator<<(std::ostream&, const State*);
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
State(const State& oth)
|
||||
: label(oth.label)
|
||||
, rule(oth.rule)
|
||||
, next(oth.next)
|
||||
, link(oth.link)
|
||||
, depth(oth.depth)
|
||||
, kCount(oth.kCount)
|
||||
, kernel(oth.kernel)
|
||||
, isBase(oth.isBase)
|
||||
, go(oth.go)
|
||||
, action(oth.action)
|
||||
{
|
||||
}
|
||||
State& operator = (const State& oth)
|
||||
{
|
||||
new(this) State(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class DFA
|
||||
{
|
||||
|
||||
public:
|
||||
uint lbChar;
|
||||
uint ubChar;
|
||||
uint nStates;
|
||||
State *head, **tail;
|
||||
State *toDo;
|
||||
|
||||
public:
|
||||
DFA(Ins*, uint, uint, uint, Char*);
|
||||
~DFA();
|
||||
void addState(State**, State*);
|
||||
State *findState(Ins**, uint);
|
||||
void split(State*);
|
||||
|
||||
void findSCCs();
|
||||
void findBaseState();
|
||||
void emit(std::ostream&, uint);
|
||||
|
||||
friend std::ostream& operator<<(std::ostream&, const DFA&);
|
||||
friend std::ostream& operator<<(std::ostream&, const DFA*);
|
||||
|
||||
#ifdef PEDANTIC
|
||||
DFA(const DFA& oth)
|
||||
: lbChar(oth.lbChar)
|
||||
, ubChar(oth.ubChar)
|
||||
, nStates(oth.nStates)
|
||||
, head(oth.head)
|
||||
, tail(oth.tail)
|
||||
, toDo(oth.toDo)
|
||||
{
|
||||
}
|
||||
DFA& operator = (const DFA& oth)
|
||||
{
|
||||
new(this) DFA(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
inline Action::Action(State *s) : state(s)
|
||||
{
|
||||
delete s->action;
|
||||
s->action = this;
|
||||
}
|
||||
|
||||
inline Action::~Action()
|
||||
{
|
||||
}
|
||||
|
||||
inline bool Action::isRule() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Action::isMatch() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Action::isInitial() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Action::readAhead() const
|
||||
{
|
||||
return !isMatch() || (state && state->next && state->next->action && !state->next->action->isRule());
|
||||
}
|
||||
|
||||
inline Match::Match(State *s) : Action(s)
|
||||
{ }
|
||||
|
||||
inline bool Match::isMatch() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline Enter::Enter(State *s, uint l) : Action(s), label(l)
|
||||
{ }
|
||||
|
||||
inline Initial::Initial(State *s, uint l, bool b) : Enter(s, l), setMarker(b)
|
||||
{ }
|
||||
|
||||
inline bool Initial::isInitial() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline Save::Save(State *s, uint i) : Match(s), selector(i)
|
||||
{ }
|
||||
|
||||
inline bool Save::isMatch() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Rule::isRule() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &o, const State *s)
|
||||
{
|
||||
return o << *s;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &o, const DFA *dfa)
|
||||
{
|
||||
return o << *dfa;
|
||||
}
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
#endif
|
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.}
|
||||
}
|
83
tools/re2c/examples/001_upn_calculator/README
Normal file
83
tools/re2c/examples/001_upn_calculator/README
Normal file
|
@ -0,0 +1,83 @@
|
|||
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 :-)
|
84
tools/re2c/examples/001_upn_calculator/calc_001.re
Normal file
84
tools/re2c/examples/001_upn_calculator/calc_001.re
Normal file
|
@ -0,0 +1,84 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
69
tools/re2c/examples/001_upn_calculator/calc_002.re
Normal file
69
tools/re2c/examples/001_upn_calculator/calc_002.re
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* 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 occurence. 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;
|
||||
}
|
||||
}
|
61
tools/re2c/examples/001_upn_calculator/calc_003.re
Normal file
61
tools/re2c/examples/001_upn_calculator/calc_003.re
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
78
tools/re2c/examples/001_upn_calculator/calc_004.re
Normal file
78
tools/re2c/examples/001_upn_calculator/calc_004.re
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
144
tools/re2c/examples/001_upn_calculator/calc_005.re
Normal file
144
tools/re2c/examples/001_upn_calculator/calc_005.re
Normal file
|
@ -0,0 +1,144 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
162
tools/re2c/examples/001_upn_calculator/calc_006.s.re
Normal file
162
tools/re2c/examples/001_upn_calculator/calc_006.s.re
Normal file
|
@ -0,0 +1,162 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
135
tools/re2c/examples/001_upn_calculator/calc_007.b.re
Normal file
135
tools/re2c/examples/001_upn_calculator/calc_007.b.re
Normal file
|
@ -0,0 +1,135 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
158
tools/re2c/examples/001_upn_calculator/calc_008.b.re
Normal file
158
tools/re2c/examples/001_upn_calculator/calc_008.b.re
Normal file
|
@ -0,0 +1,158 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
54
tools/re2c/examples/001_upn_calculator/windows/HiResTimer.h
Normal file
54
tools/re2c/examples/001_upn_calculator/windows/HiResTimer.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* @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
|
291
tools/re2c/examples/001_upn_calculator/windows/main.b.re
Normal file
291
tools/re2c/examples/001_upn_calculator/windows/main.b.re
Normal file
|
@ -0,0 +1,291 @@
|
|||
/* 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;
|
||||
}
|
21
tools/re2c/examples/002_strip_comments/README
Normal file
21
tools/re2c/examples/002_strip_comments/README
Normal file
|
@ -0,0 +1,21 @@
|
|||
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
|
147
tools/re2c/examples/002_strip_comments/strip_001.s.re
Normal file
147
tools/re2c/examples/002_strip_comments/strip_001.s.re
Normal file
|
@ -0,0 +1,147 @@
|
|||
/* 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;
|
||||
}
|
||||
}
|
162
tools/re2c/examples/002_strip_comments/strip_002.s.re
Normal file
162
tools/re2c/examples/002_strip_comments/strip_002.s.re
Normal file
|
@ -0,0 +1,162 @@
|
|||
/* re2c lesson 002_strip_comments, strip_002.s, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- complexity
|
||||
. When a comment is preceeded 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 consequtive 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 continure 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;
|
||||
}
|
||||
}
|
179
tools/re2c/examples/002_strip_comments/strip_003.b.re
Normal file
179
tools/re2c/examples/002_strip_comments/strip_003.b.re
Normal file
|
@ -0,0 +1,179 @@
|
|||
/* re2c lesson 002_strip_comments, strip_003.b, (c) M. Boerger 2006 - 2007 */
|
||||
/*!ignore:re2c
|
||||
|
||||
- more complexity
|
||||
. Right now we strip out trailing white space and new lines after a comment
|
||||
block. This can be a problem when the comment block was not preceeded by
|
||||
a new line.
|
||||
. The solution is to use trailing contexts.
|
||||
|
||||
- trailing contexts
|
||||
. Re2c allows to check for a portion of input and only recognize it when it
|
||||
is followed by another portion. This is called a trailing context.
|
||||
. The trailing context is not part of the identified input. That means that
|
||||
it follows exactly at the cursor. A consequence is that the scanner has
|
||||
already read more input and on the next run you need to restore begining
|
||||
of input, in our case s.tok, from the cursor, here s.cur, rather then
|
||||
restoring to the beginning of the buffer. This way the scanner can reuse
|
||||
the portion it has already read.
|
||||
. The position of the trailing context is stored in YYCTXMARKER for which
|
||||
a pointer variable needs to be provided.
|
||||
. As with YYMARKER the corrsponding variable needs to be corrected if we
|
||||
shift in some buffer.
|
||||
. Still this is not all we need to solve the problem. What is left is that
|
||||
the information whether we detected a trailing context was detected has to
|
||||
be stored somewhere. This is done by the new variable nlcomment.
|
||||
|
||||
- formatting
|
||||
. Until now we only used single line expression code and we always had the
|
||||
opening { on the same line as the rule itself. If we have multiline rule
|
||||
code and care for formatting we can no longer rely on re2c. Now we have
|
||||
to indent the rule code ourself. Also we need to take care of the opening
|
||||
{. If we keep it on the same line as the rule then re2c will indent it
|
||||
correctly and the emitted #line informations will be correct. If we place
|
||||
it on the next line then the #line directive will also point to that line
|
||||
and not to the rule.
|
||||
*/
|
||||
|
||||
#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 YYCTXMARKER s.ctx
|
||||
#define YYFILL(n) { if ((res = fill(&s, n)) >= 0) break; }
|
||||
|
||||
typedef struct Scanner
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char *cur, *tok, *lim, *eof, *ctx, *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;
|
||||
s->ctx -= 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;
|
||||
int nlcomment = 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; }
|
||||
NL / "/""*" { echo(&s); nlcomment = 1; continue; }
|
||||
"/" "*" { 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? "/" "*" { goto comment; }
|
||||
NL {
|
||||
if (!nlcomment)
|
||||
{
|
||||
echo(&s);
|
||||
}
|
||||
nlcomment = 0;
|
||||
continue;
|
||||
}
|
||||
WS { goto commentws; }
|
||||
ANY { echo(&s); nlcomment = 0; 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;
|
||||
}
|
||||
}
|
|
@ -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,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);
|
||||
}
|
35
tools/re2c/examples/input_custom/fixed.re
Normal file
35
tools/re2c/examples/input_custom/fixed.re
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Build with "--input custom" re2c switch.
|
||||
//
|
||||
// This is an example of handling fixed-length buffer with "--input custom":
|
||||
// on each YYPEEK we check for the end of input, thus YYFILL generation
|
||||
// can be safely suppressed.
|
||||
//
|
||||
// Note that YYLIMIT points not to terminating NULL, but to the previous
|
||||
// character: we emulate the case when input has no terminating NULL.
|
||||
//
|
||||
// For a real-life example see https://github.com/sopyer/mjson
|
||||
// or mjson.re from re2c test collection.
|
||||
|
||||
bool lex (const char * cursor, const char * const limit)
|
||||
{
|
||||
const char * marker;
|
||||
const char * ctxmarker;
|
||||
# define YYCTYPE char
|
||||
# define YYPEEK() (cursor >= limit ? 0 : *cursor)
|
||||
# define YYSKIP() ++cursor
|
||||
# define YYBACKUP() marker = cursor
|
||||
# define YYBACKUPCTX() ctxmarker = cursor
|
||||
# define YYRESTORE() cursor = marker
|
||||
# define YYRESTORECTX() cursor = ctxmarker
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
"int buffer " / "[" [0-9]+ "]" { return true; }
|
||||
* { return false; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
char buffer [] = "int buffer [1024]";
|
||||
return !lex (buffer, buffer + sizeof (buffer) - 1);
|
||||
}
|
20
tools/re2c/examples/input_custom/simple/README
Normal file
20
tools/re2c/examples/input_custom/simple/README
Normal file
|
@ -0,0 +1,20 @@
|
|||
Build with "--input custom" re2c switch.
|
||||
|
||||
These are three examples of "--input custom" usage:
|
||||
|
||||
- input_custom_default.re:
|
||||
implements default re2c input model (pointers to plain buffer)
|
||||
|
||||
- input_custom_fgetc:
|
||||
implements C-style file input (using <stdio.h>)
|
||||
|
||||
- input_custom_fgetc:
|
||||
implements std::istringstream input
|
||||
|
||||
Note that these examples are very simple and don't need
|
||||
to implement YYFILL; the only reason they don't use
|
||||
"re2c:yyfill:enable = 0;" is to keep YYLESSTHAN and YYLIMIT
|
||||
(for the sake of example).
|
||||
|
||||
In real-life programs one will need to care for correct
|
||||
end-of-input handling.
|
24
tools/re2c/examples/input_custom/simple/default.re
Normal file
24
tools/re2c/examples/input_custom/simple/default.re
Normal file
|
@ -0,0 +1,24 @@
|
|||
bool lex (const char * cursor, const char * const limit)
|
||||
{
|
||||
const char * marker;
|
||||
const char * ctxmarker;
|
||||
# define YYCTYPE char
|
||||
# define YYPEEK() *cursor
|
||||
# define YYSKIP() ++cursor
|
||||
# define YYBACKUP() marker = cursor
|
||||
# define YYBACKUPCTX() ctxmarker = cursor
|
||||
# define YYRESTORE() cursor = marker
|
||||
# define YYRESTORECTX() cursor = ctxmarker
|
||||
# define YYLESSTHAN(n) limit - cursor < n
|
||||
# define YYFILL(n) {}
|
||||
/*!re2c
|
||||
"int buffer " / "[" [0-9]+ "]" { return true; }
|
||||
* { return false; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
char buffer [] = "int buffer [1024]";
|
||||
return !lex (buffer, buffer + sizeof (buffer));
|
||||
}
|
43
tools/re2c/examples/input_custom/simple/fgetc.re
Normal file
43
tools/re2c/examples/input_custom/simple/fgetc.re
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include <stdio.h>
|
||||
|
||||
char peek (FILE * f)
|
||||
{
|
||||
char c = fgetc (f);
|
||||
ungetc (c, f);
|
||||
return c;
|
||||
}
|
||||
|
||||
bool lex (FILE * f, const long limit)
|
||||
{
|
||||
long marker;
|
||||
long ctxmarker;
|
||||
# define YYCTYPE char
|
||||
# define YYPEEK() peek (f)
|
||||
# define YYSKIP() fgetc (f)
|
||||
# define YYBACKUP() marker = ftell (f)
|
||||
# define YYBACKUPCTX() ctxmarker = ftell (f)
|
||||
# define YYRESTORE() fseek (f, marker, SEEK_SET)
|
||||
# define YYRESTORECTX() fseek (f, ctxmarker, SEEK_SET)
|
||||
# define YYLESSTHAN(n) limit - ftell (f) < n
|
||||
# define YYFILL(n) {}
|
||||
/*!re2c
|
||||
"int buffer " / "[" [0-9]+ "]" { return true; }
|
||||
* { return false; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
const char buffer [] = "int buffer [1024]";
|
||||
const char fn [] = "input.txt";
|
||||
|
||||
FILE * f = fopen (fn, "w");
|
||||
fwrite (buffer, 1, sizeof (buffer), f);
|
||||
fclose (f);
|
||||
|
||||
f = fopen (fn, "rb");
|
||||
int result = !lex (f, sizeof (buffer));
|
||||
fclose (f);
|
||||
|
||||
return result;
|
||||
}
|
27
tools/re2c/examples/input_custom/simple/istringstream.re
Normal file
27
tools/re2c/examples/input_custom/simple/istringstream.re
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <sstream>
|
||||
|
||||
bool lex (std::istringstream & is, const std::streampos limit)
|
||||
{
|
||||
std::streampos marker;
|
||||
std::streampos ctxmarker;
|
||||
# define YYCTYPE char
|
||||
# define YYPEEK() is.peek ()
|
||||
# define YYSKIP() is.ignore ()
|
||||
# define YYBACKUP() marker = is.tellg ()
|
||||
# define YYBACKUPCTX() ctxmarker = is.tellg ()
|
||||
# define YYRESTORE() is.seekg (marker)
|
||||
# define YYRESTORECTX() is.seekg (ctxmarker)
|
||||
# define YYLESSTHAN(n) limit - is.tellg () < n
|
||||
# define YYFILL(n) {}
|
||||
/*!re2c
|
||||
"int buffer " / "[" [0-9]+ "]" { return true; }
|
||||
* { return false; }
|
||||
*/
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
const char buffer [] = "int buffer [1024]";
|
||||
std::istringstream is (buffer);
|
||||
return !lex (is, sizeof (buffer));
|
||||
}
|
|
@ -11,13 +11,14 @@ typedef unsigned char uchar;
|
|||
#define YYCURSOR cursor
|
||||
#define YYLIMIT s->lim
|
||||
#define YYMARKER s->ptr
|
||||
#define YYCTXMARKER s->ctx
|
||||
#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;
|
||||
uchar *bot, *tok, *ptr, *ctx, *cur, *pos, *lim, *top, *eof;
|
||||
uint line;
|
||||
} Scanner;
|
||||
|
|
@ -227,13 +227,13 @@ public:
|
|||
start:
|
||||
|
||||
/*!re2c
|
||||
|
||||
re2c:startlabel = 1;
|
||||
eol = "\n";
|
||||
eof = "\000";
|
||||
digit = [0-9];
|
||||
integer = digit+;
|
||||
alpha = [A-Za-z_];
|
||||
any = [\000-\0377];
|
||||
any = [\000-\377];
|
||||
space = [ \h\t\v\f\r];
|
||||
|
||||
"if" { SEND(kIf); }
|
|
@ -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,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,73 +0,0 @@
|
|||
/* $Id: globals.h 713 2007-04-29 15:33:47Z helly $ */
|
||||
#ifndef _globals_h
|
||||
#define _globals_h
|
||||
|
||||
#include "basics.h"
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "stream_lc.h"
|
||||
#include "code_names.h"
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
extern file_info sourceFileInfo;
|
||||
extern file_info outputFileInfo;
|
||||
|
||||
extern bool bFlag;
|
||||
extern bool dFlag;
|
||||
extern bool eFlag;
|
||||
extern bool fFlag;
|
||||
extern bool gFlag;
|
||||
extern bool iFlag;
|
||||
extern bool sFlag;
|
||||
extern bool uFlag;
|
||||
extern bool wFlag;
|
||||
|
||||
extern bool bNoGenerationDate;
|
||||
|
||||
extern bool bSinglePass;
|
||||
extern bool bFirstPass;
|
||||
extern bool bLastPass;
|
||||
|
||||
extern bool bUsedYYAccept;
|
||||
extern bool bUsedYYMaxFill;
|
||||
extern bool bUsedYYMarker;
|
||||
|
||||
extern bool bUseStartLabel;
|
||||
extern std::string startLabelName;
|
||||
extern std::string labelPrefix;
|
||||
extern std::string yychConversion;
|
||||
extern uint maxFill;
|
||||
extern uint next_label;
|
||||
extern uint cGotoThreshold;
|
||||
|
||||
/* configurations */
|
||||
extern uint topIndent;
|
||||
extern std::string indString;
|
||||
extern bool yybmHexTable;
|
||||
extern bool bUseStateAbort;
|
||||
extern bool bUseStateNext;
|
||||
extern bool bWroteGetState;
|
||||
extern bool bUseYYFill;
|
||||
extern bool bUseYYFillParam;
|
||||
|
||||
extern uint asc2ebc[256];
|
||||
extern uint ebc2asc[256];
|
||||
|
||||
extern uint *xlat, *talx;
|
||||
|
||||
extern uint next_fill_index;
|
||||
extern uint last_fill_index;
|
||||
extern std::set<uint> vUsedLabels;
|
||||
extern re2c::CodeNames mapCodeName;
|
||||
|
||||
extern uint nRealChars;
|
||||
|
||||
extern char octCh(uint c);
|
||||
extern char hexCh(uint c);
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue