Support the predefined identifier __func__ (from C99).

This gives the name of the current function, as if the following definition appeared at the beginning of the function body:

static const char __func__[] = "function-name";
This commit is contained in:
Stephen Heumann 2021-03-02 20:01:32 -06:00
parent f19d21365a
commit 77d66ab699
4 changed files with 99 additions and 3 deletions

View File

@ -256,6 +256,18 @@ procedure TypeName; extern;
{ outputs: }
{ typeSpec - pointer to the type }
function MakeFuncIdentifier: identPtr; extern;
{ Make the predefined identifier __func__. }
{ }
{ It is inserted in the symbol table as if the following }
{ declaration appeared at the beginning of the function body: }
{ }
{ static const char __func__[] = "function-name"; }
{ }
{ This must only be called within a function body. }
{-- External unsigned math routines ----------------------------}
function lshr (x,y: longint): longint; extern;
@ -905,7 +917,9 @@ var
{if the id is not declared, create a function returning integer}
else if id = nil then begin
if token.kind = lparench then begin
if (fToken.name^ = '__func__') and (functionTable <> nil) then
id := MakeFuncIdentifier
else if token.kind = lparench then begin
fnPtr := pointer(GCalloc(sizeof(typeRecord)));
{fnPtr^.size := 0;}
{fnPtr^.saveDisp := 0;}

View File

@ -57,6 +57,18 @@ procedure AutoInit (variable: identPtr; line: integer);
{ line - line number (used for debugging) }
function MakeFuncIdentifier: identPtr;
{ Make the predefined identifier __func__. }
{ }
{ It is inserted in the symbol table as if the following }
{ declaration appeared at the beginning of the function body: }
{ }
{ static const char __func__[] = "function-name"; }
{ }
{ This must only be called within a function body. }
procedure InitParser;
{ Initialize the parser }
@ -152,6 +164,7 @@ type
var
firstCompoundStatement: boolean; {are we doing a function level compound statement?}
fType: typePtr; {return type of the current function}
functionName: stringPtr; {name of the current function}
isForwardDeclared: boolean; {is the field list component }
{ referencing a forward struct/union? }
isFunction: boolean; {is the declaration a function?}
@ -356,6 +369,8 @@ if not doingFunction then begin {if so, finish it off}
nameFound := false; {no pc_nam for the next function (yet)}
volatile := savedVolatile; {local volatile vars are out of scope}
fIsNoreturn := false; {not doing a noreturn function}
functionTable := nil;
functionName := nil;
end; {if}
PopTable; {remove this symbol table}
dispose(stPtr); {dump the record}
@ -3732,6 +3747,7 @@ if isFunction then begin
Gen0 (dc_pin);
if not isAsm then
Gen1Name(pc_ent, 0, variable^.name);
functionName := variable^.name;
nextLocalLabel := 1; {initialize GetLocalLabel}
returnLabel := GenLabel; {set up an exit point}
tempList := nil; {initialize the work label list}
@ -3792,6 +3808,7 @@ if isFunction then begin
else
GenParameters(fnType^.parameterList);
savedVolatile := volatile;
functionTable := table;
CompoundStatement(false); {process the statements}
end; {else}
end; {else}
@ -4436,6 +4453,61 @@ if variable^.class <> staticsy then begin
end; {AutoInit}
function MakeFuncIdentifier{: identPtr};
{ Make the predefined identifier __func__. }
{ }
{ It is inserted in the symbol table as if the following }
{ declaration appeared at the beginning of the function body: }
{ }
{ static const char __func__[] = "function-name"; }
{ }
{ This must only be called within a function body. }
var
lTable: symbolTablePtr; {saved copy of current symbol table}
tp: typePtr; {the type of __func__}
id: identPtr; {the identifier for __func__}
sval: longstringPtr; {the initializer string}
iPtr: initializerPtr; {the initializer}
i: integer; {loop variable}
len: integer; {string length}
begin {MakeFuncIdentifier}
lTable := table;
table := functionTable;
len := ord(functionName^[0]) + 1;
tp := pointer(GCalloc(sizeof(typeRecord)));
tp^.size := len;
tp^.saveDisp := 0;
tp^.isConstant := false;
tp^.kind := arrayType;
tp^.aType := constCharPtr;
tp^.elements := len;
id := NewSymbol(@'__func__', tp, staticsy, variableSpace, initialized);
sval := pointer(GCalloc(len + sizeof(integer)));
sval^.length := len;
for i := 1 to len-1 do
sval^.str[i] := functionName^[i];
sval^.str[len] := chr(0);
iPtr := pointer(GCalloc(sizeof(initializerRecord)));
iPtr^.next := nil;
iPtr^.count := 1;
iPtr^.bitdisp := 0;
iPtr^.bitsize := 0;
iPtr^.isStructOrUnion := false;
iPtr^.isConstant := true;
iPtr^.itype := cgString;
iPtr^.sval := sval;
id^.iPtr := iPtr;
table := lTable;
MakeFuncIdentifier := id;
end; {MakeFuncIdentifier}
procedure InitParser;
{ Initialize the parser }

View File

@ -47,6 +47,7 @@
{ voidPtrPtr - typeless pointer, for some type casting }
{ stringTypePtr - pointer to the base type for string }
{ constants }
{ constCharPtr - pointer to the type const char }
{ defaultStruct - default for structures with errors }
{ }
{---------------------------------------------------------------}
@ -76,12 +77,13 @@ var
noDeclarations: boolean; {have we declared anything at this level?}
table: symbolTablePtr; {current symbol table}
globalTable: symbolTablePtr; {global symbol table}
functionTable: symbolTablePtr; {table for top level of current function}
{base types}
charPtr,sCharPtr,uCharPtr,shortPtr,uShortPtr,intPtr,uIntPtr,int32Ptr,
uInt32Ptr,longPtr,uLongPtr,longLongPtr,uLongLongPtr,boolPtr,
floatPtr,doublePtr,compPtr,extendedPtr,stringTypePtr,voidPtr,
voidPtrPtr,defaultStruct: typePtr;
voidPtrPtr,constCharPtr,defaultStruct: typePtr;
{---------------------------------------------------------------}
@ -1215,6 +1217,7 @@ table := nil; {initialize the global symbol table}
PushTable;
globalTable := table;
noDeclarations := false;
functionTable := nil;
{declare base types}
new(sCharPtr); {signed char}
with sCharPtr^ do begin
@ -1369,7 +1372,7 @@ with extendedPtr^ do begin
baseType := cgExtended;
cType := ctLongDouble;
end; {with}
new(boolPtr); {_Bool}
new(boolPtr); {_Bool}
with boolPtr^ do begin
size := cgWordSize;
saveDisp := 0;
@ -1422,6 +1425,9 @@ with defaultStruct^ do begin {(for structures with errors)}
bitdisp := 0;
end; {with}
end; {with}
new(constCharPtr); {const char}
constCharPtr^ := charPtr^;
constCharPtr^.isConstant := true;
end; {InitSymbol}

View File

@ -391,6 +391,10 @@ Several new library functions in <stdlib.h> support operations on these types, a
The predefined macro __ORCAC_HAS_LONG_LONG__ is now defined, and expands to the integer constant 1. This indicates that these long long types are supported.
20. (C99) The predefined identifier __func__ is now supported, providing a way for code within a function to get the function's name. Specifically, it behaves as if the following declaration appeared at the beginning of each function body (where function-name is the name of the function):
static const char __func__[] = "function-name";
Multi-Character Character Constants
-----------------------------------