forked from OSchip/llvm-project
Implement the __TIME__ and __DATE__ builtin macros.
llvm-svn: 38597
This commit is contained in:
parent
7d6a4f6746
commit
c673f905d8
|
@ -26,26 +26,6 @@ MacroExpander::MacroExpander(LexerToken &Tok, Preprocessor &pp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// getInstantiationLoc - Return a SourceLocation that specifies a macro
|
|
||||||
/// instantiation whose physical location is PhysLoc but the logical location
|
|
||||||
/// is InstantiationLoc.
|
|
||||||
SourceLocation MacroExpander::
|
|
||||||
getInstantiationLoc(Preprocessor &PP,
|
|
||||||
SourceLocation PhysLoc, SourceLocation InstantiationLoc) {
|
|
||||||
// The token's current location indicate where the token was lexed from. We
|
|
||||||
// need this information to compute the spelling of the token, but any
|
|
||||||
// diagnostics for the expanded token should appear as if they came from
|
|
||||||
// InstantiationLoc. Pull this information together into a new SourceLocation
|
|
||||||
// that captures all of this.
|
|
||||||
unsigned CharFilePos = PhysLoc.getRawFilePos();
|
|
||||||
unsigned CharFileID = PhysLoc.getFileID();
|
|
||||||
|
|
||||||
unsigned InstantiationFileID =
|
|
||||||
PP.getSourceManager().createFileIDForMacroExp(InstantiationLoc, CharFileID);
|
|
||||||
return SourceLocation(InstantiationFileID, CharFilePos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Lex - Lex and return a token from this macro stream.
|
/// Lex - Lex and return a token from this macro stream.
|
||||||
///
|
///
|
||||||
void MacroExpander::Lex(LexerToken &Tok) {
|
void MacroExpander::Lex(LexerToken &Tok) {
|
||||||
|
@ -56,9 +36,13 @@ void MacroExpander::Lex(LexerToken &Tok) {
|
||||||
// Get the next token to return.
|
// Get the next token to return.
|
||||||
Tok = Macro.getReplacementToken(CurToken++);
|
Tok = Macro.getReplacementToken(CurToken++);
|
||||||
|
|
||||||
// Update the tokens location to include both its logical and physical
|
// The token's current location indicate where the token was lexed from. We
|
||||||
// locations.
|
// need this information to compute the spelling of the token, but any
|
||||||
Tok.SetLocation(getInstantiationLoc(PP, Tok.getLocation(), InstantiateLoc));
|
// diagnostics for the expanded token should appear as if they came from
|
||||||
|
// InstantiationLoc. Pull this information together into a new SourceLocation
|
||||||
|
// that captures all of this.
|
||||||
|
Tok.SetLocation(PP.getSourceManager().getInstantiationLoc(Tok.getLocation(),
|
||||||
|
InstantiateLoc));
|
||||||
|
|
||||||
// If this is the first token, set the lexical properties of the token to
|
// If this is the first token, set the lexical properties of the token to
|
||||||
// match the lexical properties of the macro identifier.
|
// match the lexical properties of the macro identifier.
|
||||||
|
|
|
@ -434,6 +434,8 @@ IdentifierTokenInfo *Preprocessor::RegisterBuiltinMacro(const char *Name) {
|
||||||
void Preprocessor::RegisterBuiltinMacros() {
|
void Preprocessor::RegisterBuiltinMacros() {
|
||||||
// FIXME: implement them all, including _Pragma.
|
// FIXME: implement them all, including _Pragma.
|
||||||
Ident__LINE__ = RegisterBuiltinMacro("__LINE__");
|
Ident__LINE__ = RegisterBuiltinMacro("__LINE__");
|
||||||
|
Ident__DATE__ = RegisterBuiltinMacro("__DATE__");
|
||||||
|
Ident__TIME__ = RegisterBuiltinMacro("__TIME__");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -498,8 +500,7 @@ void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
|
||||||
// Update the tokens location to include both its logical and physical
|
// Update the tokens location to include both its logical and physical
|
||||||
// locations.
|
// locations.
|
||||||
SourceLocation Loc =
|
SourceLocation Loc =
|
||||||
MacroExpander::getInstantiationLoc(*this, Identifier.getLocation(),
|
SourceMgr.getInstantiationLoc(Identifier.getLocation(), InstantiateLoc);
|
||||||
InstantiateLoc);
|
|
||||||
Identifier.SetLocation(Loc);
|
Identifier.SetLocation(Loc);
|
||||||
|
|
||||||
// Since this is not an identifier token, it can't be macro expanded, so
|
// Since this is not an identifier token, it can't be macro expanded, so
|
||||||
|
@ -516,6 +517,27 @@ void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
|
||||||
return Lex(Identifier);
|
return Lex(Identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ComputeDATE_TIME - Compute the current time, enter it into the specified
|
||||||
|
/// scratch buffer, then return DATELoc/TIMELoc locations with the position of
|
||||||
|
/// the identifier tokens inserted.
|
||||||
|
static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
|
||||||
|
ScratchBuffer *ScratchBuf) {
|
||||||
|
time_t TT = time(0);
|
||||||
|
struct tm *TM = localtime(&TT);
|
||||||
|
|
||||||
|
static const char * const Months[] = {
|
||||||
|
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
|
||||||
|
};
|
||||||
|
|
||||||
|
char TmpBuffer[100];
|
||||||
|
sprintf(TmpBuffer, "\"%s %2d %4d\"", Months[TM->tm_mon], TM->tm_mday,
|
||||||
|
TM->tm_year+1900);
|
||||||
|
DATELoc = ScratchBuf->getToken(TmpBuffer, strlen(TmpBuffer));
|
||||||
|
|
||||||
|
sprintf(TmpBuffer, "\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min, TM->tm_sec);
|
||||||
|
TIMELoc = ScratchBuf->getToken(TmpBuffer, strlen(TmpBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
|
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
|
||||||
/// as a builtin macro, handle it and return the next token as 'Tok'.
|
/// as a builtin macro, handle it and return the next token as 'Tok'.
|
||||||
void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) {
|
void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) {
|
||||||
|
@ -524,6 +546,7 @@ void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) {
|
||||||
assert(ITI && "Can't be a macro without id info!");
|
assert(ITI && "Can't be a macro without id info!");
|
||||||
char TmpBuffer[100];
|
char TmpBuffer[100];
|
||||||
|
|
||||||
|
|
||||||
if (ITI == Ident__LINE__) {
|
if (ITI == Ident__LINE__) {
|
||||||
// __LINE__ expands to a simple numeric value.
|
// __LINE__ expands to a simple numeric value.
|
||||||
sprintf(TmpBuffer, "%u", SourceMgr.getLineNumber(Tok.getLocation()));
|
sprintf(TmpBuffer, "%u", SourceMgr.getLineNumber(Tok.getLocation()));
|
||||||
|
@ -533,7 +556,24 @@ void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) {
|
||||||
Tok.SetLocation(ScratchBuf->getToken(TmpBuffer, Length, Tok.getLocation()));
|
Tok.SetLocation(ScratchBuf->getToken(TmpBuffer, Length, Tok.getLocation()));
|
||||||
Tok.SetIdentifierInfo(0);
|
Tok.SetIdentifierInfo(0);
|
||||||
Tok.ClearFlag(LexerToken::NeedsCleaning);
|
Tok.ClearFlag(LexerToken::NeedsCleaning);
|
||||||
return;
|
} else if (ITI == Ident__DATE__) {
|
||||||
|
if (!DATELoc.isValid())
|
||||||
|
ComputeDATE_TIME(DATELoc, TIMELoc, ScratchBuf);
|
||||||
|
Tok.SetKind(tok::string_literal);
|
||||||
|
Tok.SetLength(strlen("\"Mmm dd yyyy\""));
|
||||||
|
Tok.SetLocation(SourceMgr.getInstantiationLoc(DATELoc, Tok.getLocation()));
|
||||||
|
Tok.SetIdentifierInfo(0);
|
||||||
|
Tok.ClearFlag(LexerToken::NeedsCleaning);
|
||||||
|
|
||||||
|
} else if (ITI == Ident__TIME__) {
|
||||||
|
if (!TIMELoc.isValid())
|
||||||
|
ComputeDATE_TIME(DATELoc, TIMELoc, ScratchBuf);
|
||||||
|
Tok.SetKind(tok::string_literal);
|
||||||
|
Tok.SetLength(strlen("\"hh:mm:ss\""));
|
||||||
|
Tok.SetLocation(SourceMgr.getInstantiationLoc(TIMELoc, Tok.getLocation()));
|
||||||
|
Tok.SetIdentifierInfo(0);
|
||||||
|
Tok.ClearFlag(LexerToken::NeedsCleaning);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
assert(0 && "Unknown identifier!");
|
assert(0 && "Unknown identifier!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,13 +50,6 @@ public:
|
||||||
|
|
||||||
MacroInfo &getMacro() const { return Macro; }
|
MacroInfo &getMacro() const { return Macro; }
|
||||||
|
|
||||||
/// getInstantiationLoc - Return a SourceLocation that specifies a macro
|
|
||||||
/// instantiation whose physical location is PhysLoc but the logical location
|
|
||||||
/// is InstantiationLoc.
|
|
||||||
static SourceLocation getInstantiationLoc(Preprocessor &PP,
|
|
||||||
SourceLocation PhysLoc,
|
|
||||||
SourceLocation InstantiationLoc);
|
|
||||||
|
|
||||||
/// Lex - Lex and return a token from this macro stream.
|
/// Lex - Lex and return a token from this macro stream.
|
||||||
void Lex(LexerToken &Tok);
|
void Lex(LexerToken &Tok);
|
||||||
};
|
};
|
||||||
|
|
|
@ -94,6 +94,8 @@ class Preprocessor {
|
||||||
|
|
||||||
/// Identifiers for builtin macros.
|
/// Identifiers for builtin macros.
|
||||||
IdentifierTokenInfo *Ident__LINE__; // __LINE__
|
IdentifierTokenInfo *Ident__LINE__; // __LINE__
|
||||||
|
IdentifierTokenInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__
|
||||||
|
SourceLocation DATELoc, TIMELoc;
|
||||||
public:
|
public:
|
||||||
enum FileChangeReason {
|
enum FileChangeReason {
|
||||||
EnterFile, ExitFile, SystemHeaderPragma, RenameFile
|
EnterFile, ExitFile, SystemHeaderPragma, RenameFile
|
||||||
|
|
Loading…
Reference in New Issue