diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java index d7dbf630b3..b6af727fb0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java @@ -378,7 +378,7 @@ public class DefineTable { System.err.println("DONT Replace " + currKey + " in: " + buf); return -1; } - if (argv != null && argv.size() > 0) { + if (argv != null) { // need to scan carefully, and recursively // there shouldn't be so many globals... // could be screwed up by so many things diff --git a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj index f06e66fbe0..40de994a62 100644 --- a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj +++ b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj @@ -1566,7 +1566,7 @@ Declaration StorageClassSpecifier(Declaration specDT) : {} | | - [ ] + [ MultiLineString() ] | { @@ -1827,7 +1827,25 @@ void DeclConstant() : {} { | [ ":" ] | - ( "#" | ":" | | "(" ")" | ) + ( "#" | ":" | | "(" ")" | MultiLineString() ) +} + +Token MultiLineString() : { + Token t = null; + Token r = null; +} +{ + (t = + { + if (r == null) { + r = t; + } else { + r.image = r.image.substring(0,r.image.length()) + t.image.substring(1); + } + } + )+ + + { return r; } } void PragmaSpec() : { @@ -2076,9 +2094,12 @@ Declaration SpecifierQualifierList() : { ( dt = TypeSpecifier(dt) [ - LOOKAHEAD(SpecifierQualifierList() , { dt == null } ) + LOOKAHEAD(SpecifierQualifierList() , { dt == null || dt.getDataType() == null } ) sdt = SpecifierQualifierList() ] + [ + sdt = TypeQualifier(sdt != null ? sdt : dt) + ] ) | ( @@ -2372,7 +2393,7 @@ ArrayList ParameterList() : { ParameterDeclaration(list) ( LOOKAHEAD(2) - "," ParameterDeclaration(list) + "," ParameterDeclaration(list) )* { return list; @@ -2384,13 +2405,14 @@ void ParameterDeclaration(ArrayList list) : { Declaration dec= new Declaration(); } { + dt = DeclarationSpecifiers(dec) ( LOOKAHEAD(Declarator(dt)) dec= Declarator(dt, null) | [ dec = AbstractDeclarator(dt) ] - ) [ "=" ] + ) [ "=" ] [PragmaSpec()] { if (dec == null) { dec = new Declaration(dt); @@ -2951,7 +2973,7 @@ Object PrimaryExpression() : { void ArgumentExpressionList() : {} { - AssignmentExpression() ( "," AssignmentExpression() )* + [ PragmaSpec() ] AssignmentExpression() ( "," [ PragmaSpec() ] AssignmentExpression() )* [ PragmaSpec() ] } Object Constant() : { @@ -3016,7 +3038,7 @@ Object Constant() : { } } | - t = + t = MultiLineString() { obj = t.image; } diff --git a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/CPP/CPP.jj b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/CPP/CPP.jj index 092de2c138..9dd2911675 100644 --- a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/CPP/CPP.jj +++ b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/CPP/CPP.jj @@ -663,7 +663,9 @@ public class PreProcessor { } } if (emitExecSwitch == true) { + if (marg != null) { setArg(key, marg); + } } } @@ -1593,13 +1595,13 @@ PPToken LineInfo() : {Token t; Token u;} } -PPToken Define() : {Token t,u=null,v=null,w=null,x=null;Vector dargs = new Vector();} +PPToken Define() : {Token t,u=null,v=null,w=null,x=null;Vector dargs = null; } { (LOOKAHEAD(2) // supports current lexer (t= - [LOOKAHEAD(2) ((u=MacroArgs(){dargs.add(u);})+ | u=MacroVals() ) + [LOOKAHEAD(2) ({u=new Token(); if (dargs==null) { dargs = new Vector(); }} ( u=MacroArgs() { dargs.add(u);})* | u=MacroVals() ) [(w=MacroVals(){ if (x==null) { - if (dargs.size()>0) { + if (dargs != null) { x=w; } else { x=u;x.image+=w.image; @@ -1612,11 +1614,11 @@ PPToken Define() : {Token t,u=null,v=null,w=null,x=null;Vector dargs = new Vecto )+] ] ) | LOOKAHEAD(2) // questionable (t= - u=MacroArgs(){dargs.add(u);} + u=MacroArgs(){if (dargs==null) { dargs = new Vector(); } dargs.add(u);} [LOOKAHEAD(2)v=Define()]) | LOOKAHEAD(2) // questionable (t= - [ (u=MacroArgs(){dargs.add(u);})+ + [ (u=MacroArgs(){if (dargs==null) { dargs = new Vector(); } dargs.add(u);})+ [v=MacroVals()] ]) | (t= // questionable ()+ u=Define() ) @@ -1635,7 +1637,7 @@ PPToken Define() : {Token t,u=null,v=null,w=null,x=null;Vector dargs = new Vecto setDef(pt,pv); printCommentedLines(emitExecSwitch, "#define " + pt.image + " " + pv.image, "" + "DEFINED"); } else if (u!=null) { - if (dargs.size()>0) { + if (dargs != null) { PPToken pv=new PPToken(""); setMacro(pt,dargs,pv); printCommentedLines(emitExecSwitch, "#define " + pt.image + "("+dargs+") " + pv.image, "" + "DEFINED"); @@ -1648,7 +1650,7 @@ PPToken Define() : {Token t,u=null,v=null,w=null,x=null;Vector dargs = new Vecto } else { if (verboseLevel==5||verboseLevel==6) println("PreProcessor: "+curFileStackTop()+"'"+t.beginLine+": "+t.image+" aready defined. Undefine first."); } - if (dargs!=null&&dargs.size()==0) dargs = null; + return pt; } } @@ -2798,7 +2800,8 @@ TOKEN: TOKEN : { > | - "]" > + "]" > | + : MACROVALS } @@ -2806,7 +2809,7 @@ SKIP : { <_ECMT5: (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/"> : MACROARGS | <_CMT5: (~["\n","\r"])+ > : MACROARGS | <_MWSP: ","> : MACROARGS | - <_EWSP: ")"> : MACROVALS | + <_COD3: > : MACROARGS | <_MACWSP: > : MACROARGS } diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/PreProcessorTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/PreProcessorTest.java index 326b1f6f50..283d37fd39 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/PreProcessorTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/PreProcessorTest.java @@ -81,6 +81,8 @@ public class PreProcessorTest extends AbstractGenericTest { catch (ParseException e) { e.printStackTrace(); } + + System.out.println(parser.getParseMessages()); // Uncomment to print out parse results // System.err.println(baos.toString()); @@ -106,6 +108,9 @@ public class PreProcessorTest extends AbstractGenericTest { assertTrue("macro expansion _fpl(bob) failed ", results .indexOf("extern int __declspec(\"fp(\\\"l\\\", \" #bob \")\") __ifplbob;") != -1); + + assertTrue("Expanded protected macro with args", results.contains("int (getc)(FILE * );")); + assertTrue("Expanded protected macro with args", results.contains("int (getchar)(void);")); } @Test diff --git a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h index 21c74a1021..c26101d2d1 100644 --- a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h +++ b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h @@ -18,13 +18,32 @@ ** Some data types are checked. More checking of the parsed information would be beneficial at some point. **/ + /** * Check initial anonymous __func_1, is give an name blarg * Note: This must be first function for junit tests to pass **/ void blarg(int *, long[][][]); - + +/** + ** Function typedef use in function body + **/ +typedef int ExternFunc(int); + +void testFunc() +{ + ExternFunc * func = (ExternFunc*)0; +} + +void testFunc() +{ + typedef int InternFunc(int); + +// TODO InternFunc * func = (InternFunc *) 0; +} + + /** * Test arrays of anonymous functions in a structure **/ @@ -39,6 +58,7 @@ typedef struct SomeStruct { int finalMember; } SomeStruct; + /** * Test forward declaration **/ @@ -53,6 +73,19 @@ typedef struct SomeStruct { } ThatStruct; +/** + * Test name used as field + */ +struct fieldname { + unsigned char a, b, c; +}; + +struct mainname { + unsigned int field1; + struct fieldname fieldname[256]; // field with same name as struct name +}; + + /** * Anonymous function parameter definitions **/ @@ -152,6 +185,27 @@ int (__stdcall * GetSectionBlock) ( #pragma GCC poison (*(volatile uint8_t *)(0xB3)) #pragma our macros nachos (for use only within FileProvider.h) + + #pragma warning (suppress: 28128) + +int g(int a, int b, int c) +{ + return a+b+c; +} +int f(void) +{ + return g(1, + 2,3); +} + +int f(void) +{ + return g(1, +#pragma warning (suppress: 28128) + 2,3); +} + + /** ** Packing tests @@ -734,6 +788,23 @@ HandleToHandle64( return((void * __ptr64) h ); } +/** + * Test const before / after TypeName +**/ +typedef long long TEST_TYPE_A; + +void funcA(TEST_TYPE_A const * arg); + +void funcB(void) +{ + funcA((const TEST_TYPE_A *)0); +} + +void funcB(void) +{ + funcA((TEST_TYPE_A const *)0); +} + /** ** pragma usage @@ -1062,6 +1133,21 @@ unsigned char _interlockedbittestandset64(long long volatile *Base, long long Of /**/ +/** + ** Multi-Line String constants + **/ + +void singleLineStrings(void) +{ + char a[] = "Hello " "World"; +} +void multilineStrings(void) +{ + char b[] = "This is a " + "multiline string."; +} + + /** ** #line in structure/function body diff --git a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/PreProcessorTest.h b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/PreProcessorTest.h index 27f2c0819e..dfd37c4996 100644 --- a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/PreProcessorTest.h +++ b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/PreProcessorTest.h @@ -392,6 +392,27 @@ ldp LDP(( _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wmismatched-tags\"") +/** + ** Protected from macro expansion + **/ + + #define stdin (&__iob[0]) +#define stdout (&__iob[1]) + +int __filbuf(FILE * /*stream*/); + +#define getc(p) \ + (--((p)->__icnt) >= 0 ? *((p)->__ptr)++ : __filbuf(p)) +#ifndef __cplusplus +int (getc)(FILE * /*stream*/); +#endif + +#define getchar() getc(stdin) +#ifndef __cplusplus +int (getchar)(void); +#endif + + /** ** Vararg defined **/