From 77d66ab69902c68785827b333153d2abe56f2c3e Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Tue, 2 Mar 2021 20:01:32 -0600 Subject: [PATCH] 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"; --- Expression.pas | 16 ++++++++++- Parser.pas | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ Symbol.pas | 10 +++++-- cc.notes | 4 +++ 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/Expression.pas b/Expression.pas index 9d8ab0e..e118b35 100644 --- a/Expression.pas +++ b/Expression.pas @@ -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;} diff --git a/Parser.pas b/Parser.pas index d8d8813..d6e5652 100644 --- a/Parser.pas +++ b/Parser.pas @@ -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 } diff --git a/Symbol.pas b/Symbol.pas index 5316e3e..f8ad3fb 100644 --- a/Symbol.pas +++ b/Symbol.pas @@ -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} diff --git a/cc.notes b/cc.notes index f7b497c..e390fa4 100644 --- a/cc.notes +++ b/cc.notes @@ -391,6 +391,10 @@ Several new library functions in 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 -----------------------------------