├── .gitignore ├── LICENSE.txt ├── README.asc ├── bison ├── 01-destructor.patch ├── 02-location.patch ├── 03-yylen.patch ├── 3.0.2 │ └── lalr1.java ├── Position.java ├── README ├── calc.y └── lalr1.java ├── build.xml ├── c99.ipr ├── cpp.sh ├── gen-parser.sh ├── java ├── .gitignore ├── c99j │ ├── c99j.iml │ ├── src │ │ ├── META-INF │ │ │ └── MANIFEST.MF │ │ └── c99 │ │ │ ├── CompEnv.java │ │ │ ├── CompilerLimits.java │ │ │ ├── CompilerOptions.java │ │ │ ├── ExtAttr.java │ │ │ ├── ExtAttrDef.java │ │ │ ├── ExtAttributes.java │ │ │ ├── OptResult.java │ │ │ ├── Platform.java │ │ │ ├── Types.java │ │ │ ├── driver │ │ │ └── Parser.java │ │ │ └── parser │ │ │ ├── .gitignore │ │ │ ├── AstActions.java │ │ │ ├── BaseActions.java │ │ │ ├── BisonLexer.java │ │ │ ├── Decl.java │ │ │ ├── DeclActions.java │ │ │ ├── EnumConstDecl.java │ │ │ ├── EnumScope.java │ │ │ ├── ExprActions.java │ │ │ ├── Linkage.java │ │ │ ├── ParamScope.java │ │ │ ├── ParserActions.java │ │ │ ├── Position.java │ │ │ ├── Scope.java │ │ │ ├── SymTable.java │ │ │ ├── Symbol.java │ │ │ ├── TreeActions.java │ │ │ ├── Trees.java │ │ │ ├── ast │ │ │ ├── Ast.java │ │ │ ├── Ast0.java │ │ │ ├── Ast1.java │ │ │ ├── Ast2.java │ │ │ ├── Ast3.java │ │ │ ├── Ast4.java │ │ │ └── AstN.java │ │ │ └── tree │ │ │ ├── ExprFormatter.java │ │ │ ├── TDeclSpec.java │ │ │ ├── TDeclaration.java │ │ │ ├── TDeclarator.java │ │ │ ├── TExpr.java │ │ │ ├── TIdent.java │ │ │ ├── TIdentList.java │ │ │ ├── TSpecAttrNode.java │ │ │ ├── TSpecDeclNode.java │ │ │ ├── TSpecNode.java │ │ │ ├── TSpecTagNode.java │ │ │ ├── TStringLiteral.java │ │ │ ├── TreeCode.java │ │ │ └── Visitor.java │ └── y │ │ ├── .gitignore │ │ ├── CParser-orig.m4.y │ │ ├── CParser.m4.y │ │ ├── defs.m4 │ │ └── fix.y ├── cpp │ ├── cpp.iml │ ├── src │ │ ├── META-INF │ │ │ └── MANIFEST.MF │ │ └── c99 │ │ │ ├── Constant.java │ │ │ ├── DummyErrorReporter.java │ │ │ ├── FatalException.java │ │ │ ├── IErrorReporter.java │ │ │ ├── ILocation.java │ │ │ ├── ISourceRange.java │ │ │ ├── Ident.java │ │ │ ├── Location.java │ │ │ ├── PlatformBits.java │ │ │ ├── SourceRange.java │ │ │ ├── TypeRules.java │ │ │ ├── TypeSpec.java │ │ │ ├── Utils.java │ │ │ ├── driver │ │ │ ├── PPSymTable.java │ │ │ └── Preprocessor.java │ │ │ └── parser │ │ │ ├── Code.java │ │ │ ├── IdentTable.java │ │ │ └── pp │ │ │ ├── Builtin.java │ │ │ ├── ConcatToken.java │ │ │ ├── IIncludeLocator.java │ │ │ ├── IPreprOptions.java │ │ │ ├── ISearchPath.java │ │ │ ├── LineReader.java │ │ │ ├── Macro.java │ │ │ ├── Misc.java │ │ │ ├── PPDefs.java │ │ │ ├── PPLexer.java │ │ │ ├── PPSymCode.java │ │ │ ├── PPSymbol.java │ │ │ ├── ParamDecl.java │ │ │ ├── ParamToken.java │ │ │ ├── Prepr.java │ │ │ ├── PreprOptions.java │ │ │ ├── SearchPathFactory.java │ │ │ └── TokenList.java │ └── test │ │ └── c99 │ │ └── ConstantTest.java └── libs │ ├── hamcrest-core-1.3.jar │ └── junit-4.11.jar ├── parse.sh └── tests ├── .gitignore ├── decl ├── attr1.c ├── decl1.c ├── decl1.c.msg ├── decl10.c ├── decl2.c ├── decl2.c.msg ├── decl3.c ├── decl3.c.msg ├── decl4.c ├── decl4.c.msg ├── decl5.c ├── decl5.c.msg ├── decl6.c ├── decl6.c.msg ├── decl7.c ├── decl7.c.msg ├── decl8.c ├── decl9.c └── run-tests.sh ├── parser ├── asm1.c ├── asm2.c ├── attr1.c ├── badf1.c ├── badf2.c ├── badf3.c ├── badf4.c ├── badf5.c ├── badfunc.c ├── crash1.c ├── crash2.i ├── parse1.c └── parse2.c └── pp ├── a\nb.c ├── a\nb.c.i ├── a\nb.c.msg ├── pp-comment-1.c ├── pp-comment-1.c.i ├── pp-comment-1.c.msg ├── pp-const-1.c ├── pp-const-1.c.i ├── pp-const-1.c.msg ├── pp-const-2.c ├── pp-const-2.c.i ├── pp-const-2.c.msg ├── pp-def-1.c ├── pp-def-1.c.i ├── pp-def-1.c.msg ├── pp-def-10.c ├── pp-def-10.c.i ├── pp-def-10.c.msg ├── pp-def-2.c ├── pp-def-2.c.i ├── pp-def-2.c.msg ├── pp-def-3.c ├── pp-def-3.c.i ├── pp-def-3.c.msg ├── pp-def-4.c ├── pp-def-4.c.i ├── pp-def-4.c.msg ├── pp-def-5.c ├── pp-def-5.c.i ├── pp-def-5.c.msg ├── pp-def-6.c ├── pp-def-6.c.i ├── pp-def-6.c.msg ├── pp-def-7.c ├── pp-def-7.c.i ├── pp-def-7.c.msg ├── pp-def-8.c ├── pp-def-8.c.i ├── pp-def-8.c.msg ├── pp-def-9.c ├── pp-def-9.c.i ├── pp-def-9.c.msg ├── pp-dir-1.c ├── pp-dir-1.c.i ├── pp-dir-1.c.msg ├── pp-elif-1.c ├── pp-elif-1.c.i ├── pp-elif-1.c.msg ├── pp-error-1.c ├── pp-error-1.c.i ├── pp-error-1.c.msg ├── pp-gen-1.c ├── pp-gen-1.c.i ├── pp-gen-1.c.msg ├── pp-if-1.c ├── pp-if-1.c.i ├── pp-if-1.c.msg ├── pp-if-2.c ├── pp-if-2.c.i ├── pp-if-2.c.msg ├── pp-if-3.c ├── pp-if-3.c.i ├── pp-if-3.c.msg ├── pp-if-4.c ├── pp-if-4.c.i ├── pp-if-4.c.msg ├── pp-if-5.c ├── pp-if-5.c.i ├── pp-if-5.c.msg ├── pp-inc-1.c ├── pp-inc-1.c.i ├── pp-inc-1.c.msg ├── pp-line-1.c ├── pp-line-1.c.i ├── pp-line-1.c.msg ├── pp-line-2.c ├── pp-line-2.c.i ├── pp-line-2.c.msg ├── pp-line-3.c ├── pp-line-3.c.i ├── pp-line-3.c.msg ├── pp-mark-1.c ├── pp-mark-1.c.i ├── pp-mark-1.c.msg ├── pp-mark-2.c ├── pp-mark-2.c.i ├── pp-mark-2.c.msg ├── pp-mark-3.c ├── pp-mark-3.c.i ├── pp-mark-3.c.msg ├── pp-t1.c ├── pp-t1.c.i ├── pp-t1.c.msg ├── pp-t2.c ├── pp-t2.c.i ├── pp-t2.c.msg ├── pp-undef-1.c ├── pp-undef-1.c.i ├── pp-undef-1.c.msg └── run-tests.sh /.gitignore: -------------------------------------------------------------------------------- 1 | c99.iws 2 | *.swp 3 | 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014 Tzvetan Mikov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.asc: -------------------------------------------------------------------------------- 1 | = README 2 | Tzvetan Mikov 3 | 4 | == C99pp 5 | 6 | +C99pp+ is intended to be a fast, production quality C preprocessor 7 | compliant with *ISO/IEC 9899:2011* (C11) and *ISO/IEC 9899:1999* (C99). 8 | 9 | It is written in Java and can be used as a standalone application or as a library. 10 | 11 | == Status 12 | 13 | It supports the full preprocessor functionality as defined by the standard, 14 | as well as some GCC extensions like named variable arguments and comma elimination. 15 | 16 | Special attention has been paid to standard compliance and robustness. 17 | 18 | It is still considered 'alpha' quality because it is a part of a larger project 19 | which is under active development, it hasn't been packaged for easy standalone usage yet, and it still hasn't undergone extensive independent testing. 20 | 21 | == Usage 22 | 23 | A precompiled binary distribution isn't available yet. You need JDK 1.6 and Apache Ant 24 | to build the preprocessor. 25 | 26 | After getting the source, change into the root project directory and build it by running 27 | +ant+ without any parameters. 28 | 29 | On success the build will produce +java/out/artifacts/c99j_jar/c99j.jar+. It can be 30 | ran simply with +java -jar java/out/artifacts/c99j_jar/c99j.jarr+. 31 | 32 | There is a simple script +cpp.sh+ provided in the project directory which makes it easier to invoke from the directory without worrying about paths. 33 | 34 | To preprocess a file invoke it in the following manner: 35 | 36 | [source,bash] 37 | ---- 38 | $projectdir/cpp.sh -Iinclude_path -Iinclude_path input.c > input.i 39 | ---- 40 | 41 | == Motivation 42 | 43 | The C preprocessor is a part of a bigger project encompassing a C compiler and 44 | other tools written in Java. 45 | 46 | Why write yet another C preprocessor (and compiler) when so many other high quality 47 | alternatives already exist? 48 | 49 | First of all, because it is fun. Contributing to an existing project like GCC, Clang, LCC, OpenWatcom, etc, at their current stage, doesn't really provide the same opportunity for 50 | delving into every exciting detail. 51 | 52 | Secondly, I chose Java because there aren't that many high quality C front-ends written in Java. 53 | Implementing another compiler in C++ (which would be my language of choice), when the excellent LLVM and Clang already exist, is too much of a stretch even for the most enthusiastic compiler developer. On the other hand, Java, for all of its horrific problems and unquestionable lack of expressive power, provides some benefits which are interesting to explore in a project of this nature. And, of course, garbage collection makes some aspects of compiler development much easier to deal with. 54 | 55 | == License 56 | 57 | All code is licensed under the MIT License included in this directory. 58 | -------------------------------------------------------------------------------- /bison/01-destructor.patch: -------------------------------------------------------------------------------- 1 | diff --git a/bison/lalr1.java b/bison/lalr1.java 2 | index bd32fa7..24408cf 100644 3 | --- a/bison/lalr1.java 4 | +++ b/bison/lalr1.java 5 | @@ -24,12 +24,12 @@ b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java], 6 | # non-used flags. 7 | b4_parse_trace_if([0], [0]) 8 | 9 | -m4_define([b4_symbol_no_destructor_assert], 10 | -[b4_symbol_if([$1], [has_destructor], 11 | - [b4_fatal([%s: %s: %%destructor does not make sense in Java], 12 | - [b4_skeleton], 13 | - [b4_symbol_action_location([$1], [destructor])])])]) 14 | -b4_symbol_foreach([b4_symbol_no_destructor_assert]) 15 | +#m4_define([b4_symbol_no_destructor_assert], 16 | +#[b4_symbol_if([$1], [has_destructor], 17 | +# [b4_fatal([%s: %s: %%destructor does not make sense in Java], 18 | +# [b4_skeleton], 19 | +# [b4_symbol_action_location([$1], [destructor])])])]) 20 | +#b4_symbol_foreach([b4_symbol_no_destructor_assert]) 21 | 22 | # Setup some macros for api.push-pull. 23 | b4_percent_define_default([[api.push-pull]], [[pull]]) 24 | @@ -69,6 +69,7 @@ m4_define([b4_define_state],[[ 25 | int yystate = 0; 26 | YYStack yystack = new YYStack (); 27 | int label = YYNEWSTATE; 28 | + ]b4_push_if([int retval = YYABORT],[boolean retval = false])[; 29 | 30 | /* Error handling. */ 31 | int yynerrs_ = 0; 32 | @@ -608,7 +609,7 @@ b4_dollar_popdef[]dnl 33 | 34 | boolean push_token_consumed = true; 35 | ]])[ 36 | - for (;;) 37 | + parse_loop: for (;;) 38 | switch (label) 39 | { 40 | /* New state. Unlike in the C/C++ skeletons, the state is already 41 | @@ -620,8 +621,7 @@ b4_dollar_popdef[]dnl 42 | 43 | /* Accept? */ 44 | if (yystate == yyfinal_) 45 | - ]b4_push_if([{label = YYACCEPT; break;}], 46 | - [return true;])[ 47 | + {label = YYACCEPT; break;} 48 | 49 | /* Take a decision. First try without lookahead. */ 50 | yyn = yypact_[yystate]; 51 | @@ -747,11 +747,15 @@ b4_dollar_popdef[]dnl 52 | { 53 | /* Return failure if at end of input. */ 54 | if (yychar == Lexer.EOF) 55 | - ]b4_push_if([{label = YYABORT; break;}],[return false;])[ 56 | + {label = YYABORT; break;} 57 | } 58 | else 59 | + { 60 | + yydestruct ("Error: discarding", 61 | + yytoken, yylval]b4_locations_if([, yylloc])[); 62 | yychar = yyempty_; 63 | } 64 | + } 65 | 66 | /* Else will try to reuse lookahead token after shifting the error 67 | token. */ 68 | @@ -795,9 +799,11 @@ b4_dollar_popdef[]dnl 69 | /* Pop the current state because it cannot handle the 70 | * error token. */ 71 | if (yystack.height == 0) 72 | - ]b4_push_if([{label = YYABORT; break;}],[return false;])[ 73 | + {label = YYABORT; break;} 74 | 75 | ]b4_locations_if([yyerrloc = yystack.locationAt (0);])[ 76 | + yydestruct ("Error: popping", 77 | + yystos_[yystate], yystack.valueAt(0)]b4_locations_if([, yystack.locationAt (0)])[); 78 | yystack.pop (); 79 | yystate = yystack.stateAt (0); 80 | if (yydebug > 0) 81 | @@ -826,15 +832,39 @@ b4_dollar_popdef[]dnl 82 | 83 | /* Accept. */ 84 | case YYACCEPT: 85 | - ]b4_push_if([this.push_parse_initialized = false; return YYACCEPT;], 86 | - [return true;])[ 87 | + ]b4_push_if([this.push_parse_initialized = false; retval = YYACCEPT;], 88 | + [retval = true;])[ 89 | + break parse_loop; 90 | 91 | /* Abort. */ 92 | case YYABORT: 93 | - ]b4_push_if([this.push_parse_initialized = false; return YYABORT;], 94 | - [return false;])[ 95 | + ]b4_push_if([this.push_parse_initialized = false; retval = YYABORT;], 96 | + [retval = false;])[ 97 | + break parse_loop; 98 | } 99 | -} 100 | + 101 | + if (yychar != yyempty_) 102 | + { 103 | + /* Make sure we have latest lookahead translation. See comments at 104 | + user semantic actions for why this is necessary. */ 105 | + yytoken = yytranslate_(yychar); 106 | + yydestruct ("Cleanup: discarding lookahead", 107 | + yytoken, yylval]b4_locations_if([, yylloc])[); 108 | + } 109 | + /* Do not reclaim the symbols of the rule whose action triggered 110 | + this YYABORT or YYACCEPT. */ 111 | + yystack.pop(yylen); 112 | + if (yydebug > 0) 113 | + yystack.print (yyDebugStream); 114 | + while (yystack.height > 0) 115 | + { 116 | + yydestruct ("Cleanup: popping", 117 | + yystos_[yystack.stateAt(0)], yystack.valueAt(0)]b4_locations_if([, yystack.locationAt(0)])[); 118 | + yystack.pop(1); 119 | + } 120 | + 121 | + return retval; 122 | + } 123 | ]b4_push_if([[ 124 | boolean push_parse_initialized = false; 125 | 126 | @@ -984,7 +1014,50 @@ b4_both_if([[ 127 | ]])[ 128 | return "syntax error"; 129 | } 130 | +] 131 | +m4_define_default([b4_symbol_value],[$1]) 132 | +m4_define([b4_symbol_action], 133 | +[b4_symbol_if([$1], [has_$2], 134 | +[b4_dollar_pushdef([yyvaluep], 135 | + b4_symbol_if([$1], [has_type], 136 | + [m4_dquote(b4_symbol([$1], [type]))]), 137 | + [yylocationp])dnl 138 | + b4_symbol_case_([$1])[]dnl 139 | +b4_syncline([b4_symbol([$1], [$2_line])], ["b4_symbol([$1], [$2_file])"]) 140 | + b4_symbol([$1], [$2]) 141 | +b4_syncline([@oline@], [@ofile@]) 142 | + break; 143 | + 144 | +b4_dollar_popdef[]dnl 145 | +])]) 146 | +m4_define([b4_symbol_actions], 147 | +[m4_pushdef([b4_actions_], m4_expand([b4_symbol_foreach([b4_symbol_$1])]))dnl 148 | +m4_ifval(m4_defn([b4_actions_]), 149 | +[switch (m4_default([$2], [yytype])) 150 | + { 151 | + m4_defn([b4_actions_]) 152 | + default: 153 | + break; 154 | + }dnl 155 | +], 156 | +[])dnl 157 | +m4_popdef([b4_actions_])dnl 158 | +]) 159 | +[ 160 | + // Release the memory associated to this symbol 161 | + private final void yydestruct ( String yymsg, int yytype, ]b4_yystype[ yyvaluep]dnl 162 | +b4_locations_if([, ]b4_location_type[ yylocationp])[]dnl 163 | +[ ) 164 | + { 165 | + if (yymsg == null) 166 | + yymsg = "Deleting"; 167 | + if (yydebug > 0) 168 | + yy_symbol_print( yymsg, yytype, yyvaluep]b4_locations_if([, yylocationp])[ ); 169 | + 170 | + ]b4_symbol_actions([destructor])[ 171 | + }] 172 | 173 | +[ 174 | /** 175 | * Whether the given yypact_ value indicates a defaulted state. 176 | * @@param yyvalue the value to check 177 | -------------------------------------------------------------------------------- /bison/02-location.patch: -------------------------------------------------------------------------------- 1 | diff --git a/bison/lalr1.java b/bison/lalr1.java 2 | index b296860..e776ae8 100644 3 | --- a/bison/lalr1.java 4 | +++ b/bison/lalr1.java 5 | @@ -133,7 +133,7 @@ b4_locations_if([[ 6 | * Locations represent a part of the input through the beginning 7 | * and ending positions. 8 | */ 9 | - public class ]b4_location_type[ { 10 | + public static final class ]b4_location_type[ { 11 | /** 12 | * The first, inclusive, position in the range. 13 | */ 14 | @@ -169,6 +169,8 @@ b4_locations_if([[ 15 | * method. 16 | */ 17 | public String toString () { 18 | + if (begin == null) 19 | + return ""; 20 | if (begin.equals (end)) 21 | return begin.toString (); 22 | else 23 | -------------------------------------------------------------------------------- /bison/03-yylen.patch: -------------------------------------------------------------------------------- 1 | commit 176abb92ec87657a0e4693780215f98defa9bd75 2 | Author: Tzvetan Mikov 3 | Date: Wed Aug 6 12:39:55 2014 -0700 4 | 5 | bison/lalr1.java: BUGFIX: yylen wasn't cleared after yyaction() 6 | 7 | The translation from the C parser missed a tiny detail: yylen is 8 | passed to yyaction() as a parameter, so clearing it inside yyaction() 9 | has no effect. 10 | 11 | So, we move the clearing outside. 12 | 13 | diff --git a/bison/lalr1.java b/bison/lalr1.java 14 | index 1060fb7..dfe60db 100644 15 | --- a/bison/lalr1.java 16 | +++ b/bison/lalr1.java 17 | @@ -496,7 +496,7 @@ b4_define_state])[ 18 | yy_symbol_print ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[); 19 | 20 | yystack.pop (yylen); 21 | - yylen = 0; 22 | + // yylen = 0; 23 | 24 | /* Shift the result of the reduction. */ 25 | int yystate = yy_lr_goto_state_ (yystack.stateAt (0), yyr1_[yyn]); 26 | @@ -723,6 +723,8 @@ b4_dollar_popdef[]dnl 27 | case YYREDUCE: 28 | yylen = yyr2_[yyn]; 29 | label = yyaction (yyn, yystack, yylen); 30 | + if (label == YYNEWSTATE) 31 | + yylen = 0; 32 | yystate = yystack.stateAt (0); 33 | break; 34 | 35 | -------------------------------------------------------------------------------- /bison/Position.java: -------------------------------------------------------------------------------- 1 | public class Position {} 2 | 3 | -------------------------------------------------------------------------------- /bison/README: -------------------------------------------------------------------------------- 1 | 3.0.2/lalr1.java 2 | unmodified Bison 3.0.2 skeleton 3 | lalr1.java 4 | modified skeleton 5 | 01-destructor.patch 6 | Patch with the modification 7 | calc.y, Position.java 8 | Files to test if the skeleton compiles. -------------------------------------------------------------------------------- /bison/calc.y: -------------------------------------------------------------------------------- 1 | 2 | %token NUM 3 | %destructor {System.out.println($$);} NUM 4 | 5 | %% 6 | prog: NUM { System.out.println( $NUM +""+ @$ ); }; 7 | 8 | 9 | -------------------------------------------------------------------------------- /cpp.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | exec java -ea -jar ${0%/*}/java/out/artifacts/cpp_jar/cpp.jar $@ 3 | -------------------------------------------------------------------------------- /gen-parser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | vis="" 3 | if [ "$1" == "-x" ]; then 4 | vis="-x" 5 | shift 6 | fi 7 | 8 | 9 | ydir="java/c99j/y" 10 | javadir="java/c99j/src/c99/parser" 11 | skeldir="bison" 12 | 13 | m4 --prefix-builtins $ydir/defs.m4 $ydir/CParser.m4.y > $ydir/CParser.y 14 | bison $vis -Wall -S $skeldir/lalr1.java $ydir/CParser.y -o $javadir/CParser.java 15 | 16 | if [ -n "$vis" ]; then 17 | mv $javadir/CParser.xml $ydir/ 18 | 19 | datadir=`bison --print-datadir` 20 | xsltproc $datadir/xslt/xml2xhtml.xsl $ydir/CParser.xml > $ydir/CParser.html 21 | fi 22 | -------------------------------------------------------------------------------- /java/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | 3 | -------------------------------------------------------------------------------- /java/c99j/c99j.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /java/c99j/src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: c99.driver.Parser 3 | -------------------------------------------------------------------------------- /java/c99j/src/c99/CompEnv.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | import c99.parser.tree.Visitor; 4 | 5 | public class CompEnv 6 | { 7 | public final CompilerOptions opts; 8 | public final IErrorReporter reporter; 9 | public final Visitor.TranslationUnit visitor; 10 | 11 | public CompEnv ( final CompilerOptions opts, final IErrorReporter reporter, Visitor.TranslationUnit visitor ) 12 | { 13 | this.opts = opts; 14 | this.reporter = reporter; 15 | this.visitor = visitor; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /java/c99j/src/c99/CompilerLimits.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public interface CompilerLimits 4 | { 5 | public static final int MAX_TYPE_DEPTH = 256; 6 | } 7 | -------------------------------------------------------------------------------- /java/c99j/src/c99/CompilerOptions.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | import c99.parser.pp.IPreprOptions; 4 | import c99.parser.pp.PreprOptions; 5 | 6 | public class CompilerOptions implements IPreprOptions 7 | { 8 | private final PreprOptions m_preprOptions = new PreprOptions(); 9 | 10 | public boolean signedChar = false; 11 | public int maxAlign = 8; 12 | public int defCodePointers = 0; // 0:near, 1:far, 2:huge 13 | public int defDataPointers = 0; // 0:near, 1:far, 2:huge 14 | 15 | public PreprOptions getPreprOptions () 16 | { 17 | return m_preprOptions; 18 | } 19 | 20 | public boolean getNoStdInc () 21 | { 22 | return m_preprOptions.getNoStdInc(); 23 | } 24 | 25 | public boolean getGccExtensions () 26 | { 27 | return m_preprOptions.getGccExtensions(); 28 | } 29 | 30 | public boolean getWarnUndef () 31 | { 32 | return m_preprOptions.getWarnUndef(); 33 | } 34 | 35 | public int getMaxIncludeDepth () 36 | { 37 | return m_preprOptions.getMaxIncludeDepth(); 38 | } 39 | } // class 40 | 41 | -------------------------------------------------------------------------------- /java/c99j/src/c99/ExtAttr.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public class ExtAttr implements Comparable 4 | { 5 | ExtAttr next; 6 | 7 | public final ExtAttrDef def; 8 | 9 | public ExtAttr ( final ExtAttrDef def ) 10 | { 11 | assert def != null; 12 | this.def = def; 13 | } 14 | 15 | public ExtAttr clone () 16 | { 17 | return new ExtAttr(this.def); 18 | } 19 | 20 | @Override public int hashCode () 21 | { 22 | return def.flag; 23 | } 24 | 25 | @Override public boolean equals ( final Object obj ) 26 | { 27 | return this == obj || obj instanceof ExtAttr && equals((ExtAttr) obj); 28 | } 29 | 30 | public boolean equals ( ExtAttr o ) 31 | { 32 | return o != null && this.def == o.def; 33 | } 34 | 35 | @Override 36 | public int compareTo ( final ExtAttr o ) 37 | { 38 | final int ah = this.hashCode(); 39 | final int bh = o.hashCode(); 40 | if (ah < bh) 41 | return -1; 42 | else if (ah > bh) 43 | return 1; 44 | else 45 | return this.def.compareTo( o.def ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /java/c99j/src/c99/ExtAttrDef.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public class ExtAttrDef implements Comparable 4 | { 5 | public static enum D { SCLASS, QUAL, SPEC } 6 | 7 | public final String name; 8 | public final D disposition; 9 | public final boolean isConst; 10 | public final int flag; 11 | 12 | public ExtAttrDef ( final String name, final D disposition, final boolean isConst, final int flag ) 13 | { 14 | assert flag != 0 : "AttrDef needs a flag"; 15 | this.name = name; 16 | this.disposition = disposition; 17 | this.isConst = isConst; 18 | this.flag = flag; 19 | } 20 | 21 | @Override 22 | public final int compareTo ( final ExtAttrDef o ) 23 | { 24 | return this == o ? 0 : name.compareTo( o.name ); 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /java/c99j/src/c99/ExtAttributes.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | import java.util.Iterator; 4 | 5 | public final class ExtAttributes implements Iterable 6 | { 7 | private ExtAttr m_head; // Sorted 8 | private int m_flags; 9 | 10 | /** 11 | * @return true if the collection changed as a result of this 12 | */ 13 | public final boolean add ( ExtAttr attr ) 14 | { 15 | assert attr.next == null; 16 | 17 | final int flag = attr.def.flag; 18 | if (attr.def.isConst) 19 | { 20 | if ((m_flags & flag) != 0) 21 | return false; 22 | m_flags |= flag; 23 | return true; 24 | } 25 | 26 | m_flags |= flag; 27 | 28 | // Insertion sort 29 | ExtAttr prev = null; 30 | ExtAttr cur = m_head; 31 | int c = -1; 32 | while (cur != null && (c = cur.compareTo(attr)) < 0) 33 | { 34 | prev = cur; 35 | cur = cur.next; 36 | } 37 | 38 | if (c == 0) 39 | return false; // Duplicate! 40 | 41 | attr.next = cur; 42 | if (prev != null) 43 | prev.next = attr; 44 | else 45 | m_head = attr; 46 | 47 | return true; 48 | } 49 | 50 | private final void clear () 51 | { 52 | m_head = null; 53 | m_flags = 0; 54 | } 55 | 56 | private final ExtAttr removeFirst () 57 | { 58 | if (m_head != null) 59 | { 60 | ExtAttr res = m_head; 61 | m_head = res.next; 62 | res.next = null; 63 | return res; 64 | } 65 | else 66 | return null; 67 | } 68 | 69 | public final void transferFrom ( /*nullable*/ ExtAttributes eas ) 70 | { 71 | if (eas == null) 72 | return; 73 | 74 | m_flags |= eas.m_flags; 75 | 76 | if (m_head == null) // Fast case: just take ownership of all elements 77 | m_head = eas.m_head; 78 | else 79 | { 80 | ExtAttr ea; 81 | while ( (ea = eas.removeFirst()) != null) 82 | add( ea ); 83 | } 84 | eas.clear(); 85 | } 86 | 87 | public final void combine ( ExtAttributes eas ) 88 | { 89 | // for ( ExtAttr ea : eas ) 90 | for ( ExtAttr ea = eas.m_head; ea != null; ea = ea.next ) 91 | add( ea.clone() ); 92 | m_flags |= eas.m_flags; 93 | } 94 | 95 | public final int flags () 96 | { 97 | return m_flags; 98 | } 99 | 100 | public final boolean same ( ExtAttributes eas ) 101 | { 102 | if (m_flags != eas.m_flags) 103 | return false; 104 | // Compare the two sorted lists 105 | ExtAttr a = m_head, b = eas.m_head; 106 | for(;;) 107 | { 108 | if (a == null) 109 | return b == null; 110 | if (!a.equals( b )) 111 | return false; 112 | a = a.next; 113 | b = b.next; 114 | } 115 | } 116 | 117 | private static final class _Iterator implements Iterator 118 | { 119 | ExtAttr m_next; 120 | 121 | private _Iterator ( final ExtAttr next ) 122 | { 123 | m_next = next; 124 | } 125 | 126 | @Override public boolean hasNext () 127 | { 128 | return m_next != null; 129 | } 130 | 131 | @Override public ExtAttr next () 132 | { 133 | ExtAttr res = m_next; 134 | m_next = res.next; 135 | return res; 136 | } 137 | 138 | @Override public void remove () 139 | {} 140 | } 141 | 142 | @Override public final _Iterator iterator () 143 | { 144 | return new _Iterator(m_head); 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /java/c99j/src/c99/OptResult.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public class OptResult 4 | { 5 | private final E m_res; 6 | 7 | public OptResult ( E e ) 8 | { 9 | m_res = e; 10 | } 11 | 12 | public E get () 13 | { 14 | return m_res; 15 | } 16 | 17 | @SuppressWarnings("unchecked") 18 | public static OptResult nullValue () 19 | { 20 | return s_null; 21 | } 22 | 23 | @SuppressWarnings("unchecked") 24 | private static final OptResult s_null = new OptResult(null); 25 | 26 | @SuppressWarnings("unchecked") 27 | public static OptResult fail () 28 | { 29 | return null; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /java/c99j/src/c99/Platform.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | import c99.parser.Trees; 4 | 5 | import java.util.HashMap; 6 | 7 | public class Platform 8 | { 9 | private final CompEnv m_env; 10 | 11 | public static final boolean LITTLE_ENDIAN = true; 12 | 13 | public static final int CHAR_BITS = 8; 14 | public static final int SHORT_BITS = 16; 15 | public static final int INT_BITS = 16; 16 | public static final int LONG_BITS = 32; 17 | public static final int LONGLONG_BITS = 64; 18 | 19 | public static final int MIN_ALIGN = 1; 20 | public static final int MAX_ALIGN = 8; 21 | 22 | private static final HashMap s_attrDefs = new HashMap(); 23 | 24 | public Platform ( CompEnv cenv ) 25 | { 26 | m_env = cenv; 27 | } 28 | 29 | private static void defAttr ( ExtAttrDef def ) 30 | { 31 | s_attrDefs.put( def.name, def ); 32 | // Per GCC, attributes are also valid with a "__" prefix and suffix 33 | s_attrDefs.put( "__" + def.name + "__", def ); 34 | } 35 | 36 | public static final int QUAL_ERROR = (1 << 0); 37 | 38 | public static final int QUAL_CDECL = (1 << 1); 39 | public static final int QUAL_STDCALL = (1 << 2); 40 | public static final int QUAL_FASTCALL = (1 << 3); 41 | 42 | public static final int QUAL_X86NEAR = (1 << 4); 43 | public static final int QUAL_X86DS = (1 << 5); 44 | public static final int QUAL_X86ES = (1 << 6); 45 | public static final int QUAL_X86CS = (1 << 7); 46 | public static final int QUAL_X86SS = (1 << 8); 47 | public static final int QUAL_X86FAR = (1 << 9); 48 | public static final int QUAL_X86HUGE = (1 << 10); 49 | 50 | public static final int QUAL_X86SEGS = QUAL_X86DS | QUAL_X86ES | QUAL_X86CS | QUAL_X86SS; 51 | 52 | private static final ExtAttrDef s_def_error = new ExtAttrDef("error", ExtAttrDef.D.QUAL, true, QUAL_ERROR); 53 | private static final ExtAttrDef s_def_cdecl = new ExtAttrDef("cdecl", ExtAttrDef.D.QUAL, true, QUAL_CDECL); 54 | private static final ExtAttrDef s_def_stdcall = new ExtAttrDef("stdcall", ExtAttrDef.D.QUAL, true, QUAL_STDCALL); 55 | private static final ExtAttrDef s_def_fastcall = new ExtAttrDef("fastcall", ExtAttrDef.D.QUAL, true, QUAL_FASTCALL); 56 | private static final ExtAttrDef s_def_x86near = new ExtAttrDef("x86near", ExtAttrDef.D.QUAL, true, QUAL_X86NEAR); 57 | private static final ExtAttrDef s_def_x86ds = new ExtAttrDef("x86ds", ExtAttrDef.D.QUAL, true, QUAL_X86DS); 58 | private static final ExtAttrDef s_def_x86es = new ExtAttrDef("x86es", ExtAttrDef.D.QUAL, true, QUAL_X86ES); 59 | private static final ExtAttrDef s_def_x86cs = new ExtAttrDef("x86cs", ExtAttrDef.D.QUAL, true, QUAL_X86CS); 60 | private static final ExtAttrDef s_def_x86ss = new ExtAttrDef("x86ss", ExtAttrDef.D.QUAL, true, QUAL_X86SS); 61 | private static final ExtAttrDef s_def_x86far = new ExtAttrDef("x86far", ExtAttrDef.D.QUAL, true, QUAL_X86FAR); 62 | private static final ExtAttrDef s_def_x86huge = new ExtAttrDef("x86huge", ExtAttrDef.D.QUAL, true, QUAL_X86HUGE); 63 | 64 | static { 65 | defAttr(s_def_cdecl); 66 | defAttr(s_def_stdcall); 67 | defAttr(s_def_fastcall); 68 | 69 | defAttr(s_def_x86near); 70 | defAttr(s_def_x86ds); 71 | defAttr(s_def_x86es); 72 | defAttr(s_def_x86cs); 73 | defAttr(s_def_x86ss); 74 | defAttr(s_def_x86far); 75 | defAttr(s_def_x86huge); 76 | 77 | } 78 | 79 | public ExtAttrDef findExtAttr ( String name ) 80 | { 81 | return s_attrDefs.get( name ); 82 | } 83 | 84 | public ExtAttr parseExtAttr ( 85 | ISourceRange locAll, ISourceRange locName, ExtAttrDef def, Trees.TreeList params 86 | ) 87 | { 88 | // None of the supported attributes have parameters 89 | if (params != null && params.size() != 0) 90 | { 91 | m_env.reporter.error( locAll, "attribute '%s' takes no parameters", def.name ); 92 | return null; 93 | } 94 | return new ExtAttr(def); 95 | } 96 | 97 | private static final ExtAttr s_errorAttr = new ExtAttr(s_def_error); 98 | private static final ExtAttr s_nearAttr = new ExtAttr(s_def_x86near); 99 | private static final ExtAttr s_dsAttr = new ExtAttr(s_def_x86ds); 100 | private static final ExtAttr s_csAttr = new ExtAttr(s_def_x86cs); 101 | private static final ExtAttr s_farAttr = new ExtAttr(s_def_x86far); 102 | private static final ExtAttr s_hugeAttr = new ExtAttr(s_def_x86huge); 103 | 104 | private void attrError ( ExtAttributes attrs, ISourceRange loc, String msg, Object... args ) 105 | { 106 | if ((attrs.flags() & QUAL_ERROR) == 0) 107 | { 108 | attrs.add( s_errorAttr ); 109 | m_env.reporter.error( loc, msg, args ); 110 | } 111 | } 112 | 113 | public void setDefaultAttrs ( Types.Qual qual ) 114 | { 115 | final ExtAttributes attrs = qual.extAttrs; 116 | 117 | assert (attrs.flags() & QUAL_X86SEGS) == 0; 118 | assert (attrs.flags() & (QUAL_X86NEAR | QUAL_X86FAR | QUAL_X86HUGE)) == 0; 119 | 120 | if (qual.spec.type == TypeSpec.FUNCTION) // Code 121 | { 122 | if (m_env.opts.defCodePointers == 0) 123 | { 124 | qual.extAttrs.add( s_nearAttr ); 125 | qual.extAttrs.add( s_csAttr ); // Near code pointers can only be "cs:" 126 | } 127 | else 128 | qual.extAttrs.add( s_farAttr ); 129 | } 130 | else // Data 131 | { 132 | if (m_env.opts.defDataPointers == 0) 133 | { 134 | qual.extAttrs.add( s_nearAttr ); 135 | qual.extAttrs.add( s_dsAttr ); 136 | } 137 | else 138 | qual.extAttrs.add( m_env.opts.defDataPointers == 1 ? s_farAttr : s_hugeAttr ); 139 | } 140 | } 141 | 142 | public boolean checkAndCompleteAttrs ( ISourceRange loc, Types.Qual qual ) 143 | { 144 | final ExtAttributes attrs = qual.extAttrs; 145 | 146 | int segs; 147 | if ((segs = attrs.flags() & QUAL_X86SEGS) != 0) 148 | { 149 | attrs.add( s_nearAttr ); 150 | if ((segs & (segs - 1)) != 0) 151 | attrError( attrs, loc, "more than one 8086 segment qualifier specified" ); 152 | } 153 | 154 | int psize; 155 | if ((psize = attrs.flags() & (QUAL_X86NEAR | QUAL_X86FAR | QUAL_X86HUGE)) != 0) 156 | { 157 | if ((psize & (psize - 1)) != 0) 158 | attrError( attrs, loc, "more than one 8086 pointer size (near/far/huge) specified" ); 159 | } 160 | 161 | if (qual.spec.type == TypeSpec.FUNCTION) // Code 162 | { 163 | // For functions we always set the necessary attributes 164 | if (psize == 0) 165 | { 166 | qual.extAttrs.add( m_env.opts.defCodePointers == 0 ? s_nearAttr : s_farAttr ); 167 | psize = attrs.flags() & (QUAL_X86NEAR | QUAL_X86FAR | QUAL_X86HUGE); 168 | } 169 | if ((psize & QUAL_X86NEAR) != 0) 170 | { 171 | if (segs == 0) 172 | qual.extAttrs.add( s_csAttr ); // Near code pointers can only be "cs:" 173 | else if ((segs & QUAL_X86CS) == 0) 174 | { 175 | qual.extAttrs.add( s_csAttr ); // Near code pointers can only be "cs:" 176 | attrError(attrs, loc, "invalid segment qualifier for a pointer to function"); 177 | } 178 | } 179 | } 180 | else // Data 181 | { 182 | // If we have a near pointer, set the segment specifier if not already set 183 | if ((psize & QUAL_X86NEAR) != 0 && segs == 0) 184 | qual.extAttrs.add( s_dsAttr ); // Near data pointers are "ds:" by default 185 | // Otherwise leave things as default 186 | } 187 | 188 | return (attrs.flags() & QUAL_ERROR) == 0; 189 | } 190 | 191 | public int pointerSize ( Types.Qual to ) 192 | { 193 | final int flags = to.extAttrs.flags(); 194 | if ((flags & (QUAL_X86HUGE | QUAL_X86FAR)) != 0) 195 | return 4; 196 | else if ((flags & QUAL_X86NEAR) != 0) 197 | return 2; 198 | else if (to.spec.type == TypeSpec.FUNCTION) 199 | return m_env.opts.defCodePointers == 0 ? 2 : 4; 200 | else 201 | return m_env.opts.defDataPointers == 0 ? 2 : 4; 202 | } 203 | 204 | /** returns the unsgned integer type able to hold the pointer */ 205 | public TypeSpec pointerUIntType ( Types.PointerSpec ptr ) 206 | { 207 | int ptrSize = pointerSize( ptr.of ); 208 | if (ptrSize <= TypeSpec.UCHAR.width) 209 | return TypeSpec.UCHAR; 210 | else if (ptrSize <= TypeSpec.UINT.width) 211 | return TypeSpec.UINT; 212 | else if (ptrSize <= TypeSpec.ULONG.width) 213 | return TypeSpec.ULONG; 214 | else 215 | return TypeSpec.ULLONG; 216 | } 217 | 218 | public int alignment ( int size ) 219 | { 220 | return Math.min(size, m_env.opts.maxAlign); 221 | } 222 | 223 | // Convert the bit offset so it matches the storage layout. 224 | 225 | /** 226 | * Convert a bit-offset in a bit-field storage unit to a number matching the 227 | * storage layout so that incrementing bit offsets are stored in incrementing 228 | * memory addresses. 229 | * @param baseType 230 | * @param offset 231 | * @return 232 | */ 233 | public int memoryBitOffset ( TypeSpec baseType, int bitOffset, int bitWidth ) 234 | { 235 | if (LITTLE_ENDIAN) 236 | return bitOffset; 237 | else // big endian 238 | return baseType.width - bitOffset - bitWidth; 239 | } 240 | 241 | public static final Constant.IntC s_minInt[] = 242 | new Constant.IntC[TypeSpec.INT_LAST.ordinal() - TypeSpec.INT_FIRST.ordinal() + 1]; 243 | public static final Constant.IntC s_maxInt[] = 244 | new Constant.IntC[TypeSpec.INT_LAST.ordinal() - TypeSpec.INT_FIRST.ordinal() + 1]; 245 | 246 | static { 247 | for ( int i = TypeSpec.INT_FIRST.ordinal(); i <= TypeSpec.INT_LAST.ordinal(); ++i ) 248 | { 249 | TypeSpec ts = TypeSpec.values()[i]; 250 | assert ts.integer; 251 | s_minInt[i - TypeSpec.INT_FIRST.ordinal()] = Constant.makeLong( ts, ts.minValue ); 252 | s_maxInt[i - TypeSpec.INT_FIRST.ordinal()] = Constant.makeLong( ts, ts.maxValue ); 253 | } 254 | } 255 | 256 | public static Constant.IntC minInt ( TypeSpec ts ) 257 | { 258 | assert ts.integer; 259 | return s_minInt[ts.ordinal() - TypeSpec.INT_FIRST.ordinal()]; 260 | } 261 | public static Constant.IntC maxInt ( TypeSpec ts ) 262 | { 263 | assert ts.integer; 264 | return s_maxInt[ts.ordinal() - TypeSpec.INT_FIRST.ordinal()]; 265 | } 266 | 267 | /** 268 | * Determine the enum base type based on platform specifics. For example, on an 8-bit CPU we might want 269 | * to use a byte to store an enum whose values fit in a byte. In the standard case for 32-bit CPUs we 270 | * just return the passed value. 271 | * 272 | * @param baseSpec 273 | * @param minValue 274 | * @param maxValue 275 | * @return 276 | */ 277 | public TypeSpec determineEnumBaseSpec ( TypeSpec baseSpec, Constant.IntC minValue, Constant.IntC maxValue ) 278 | { 279 | assert baseSpec == minValue.spec && baseSpec == maxValue.spec; 280 | 281 | if (false) 282 | return baseSpec; 283 | else 284 | { 285 | if (baseSpec.signed) 286 | { 287 | if (!minValue.fitsInLong() || !maxValue.fitsInLong()) 288 | return baseSpec; 289 | long mi = minValue.asLong(); 290 | long ma = maxValue.asLong(); 291 | 292 | for ( int i = TypeSpec.SCHAR.ordinal(); i <= TypeSpec.SLLONG.ordinal(); i += 2 ) 293 | { 294 | final TypeSpec ts = TypeSpec.values()[i]; 295 | if (mi >= ts.minValue && ma <= ts.maxValue) 296 | return ts; 297 | } 298 | } 299 | else 300 | { 301 | if (!minValue.fitsInULong() || !maxValue.fitsInULong()) 302 | return baseSpec; 303 | long ma = maxValue.asULong(); 304 | 305 | for ( int i = TypeSpec.UCHAR.ordinal(); i <= TypeSpec.ULLONG.ordinal(); i += 2 ) 306 | { 307 | final TypeSpec ts = TypeSpec.values()[i]; 308 | if (!Constant.unsignedLessThan( ts.maxValue, ma )) 309 | return ts; 310 | } 311 | } 312 | 313 | return baseSpec; 314 | } 315 | } 316 | 317 | } // class 318 | -------------------------------------------------------------------------------- /java/c99j/src/c99/driver/Parser.java: -------------------------------------------------------------------------------- 1 | package c99.driver; 2 | 3 | import c99.*; 4 | import c99.parser.*; 5 | import c99.parser.pp.Prepr; 6 | import c99.parser.pp.SearchPathFactory; 7 | import c99.parser.tree.*; 8 | 9 | import java.io.FileInputStream; 10 | import java.io.PrintWriter; 11 | import java.util.Arrays; 12 | 13 | public class Parser 14 | { 15 | public static void main ( String[] args ) 16 | { 17 | if ("--cpp".equals( args[0] )) 18 | { 19 | Preprocessor.main(Arrays.copyOfRange(args, 1, args.length)); 20 | return; 21 | } 22 | 23 | try 24 | { 25 | String fileName = null; 26 | 27 | CompilerOptions opts = new CompilerOptions(); 28 | SearchPathFactory incSearch = new SearchPathFactory(); 29 | int debugLevel = 0; 30 | 31 | for ( int i = 0; i < args.length; ++i ) 32 | { 33 | final String arg = args[i]; 34 | 35 | if ("--nostdinc".equals( arg )) 36 | opts.getPreprOptions().setNoStdInc( true ); 37 | if ("--debug".equals( arg )) 38 | debugLevel = 1; 39 | else if (arg.startsWith("-I") || arg.startsWith("-i")) 40 | { 41 | String tmp = arg.substring( 2 ); 42 | if (tmp.length() == 0) 43 | { 44 | System.err.println( "**fatal: missing argument for " + arg ); 45 | System.exit(1); 46 | } 47 | if (arg.startsWith("-I")) 48 | incSearch.addInclude( tmp ); 49 | else 50 | incSearch.addQuotedInclude(tmp); 51 | } 52 | else if (arg.startsWith("-")) 53 | { 54 | System.err.println( "**fatal: unknown command line option '"+arg +"'" ); 55 | System.exit(1); 56 | } 57 | else 58 | { 59 | if (fileName != null) 60 | { 61 | System.err.println( "**fatal: More than one input filename specified" ); 62 | System.exit(1); 63 | } 64 | fileName = arg; 65 | } 66 | } 67 | 68 | if (fileName == null) 69 | { 70 | System.err.println( "**fatal: No input filename specified" ); 71 | System.exit(1); 72 | } 73 | 74 | DummyErrorReporter reporter = new DummyErrorReporter(); 75 | SymTable symTable = new SymTable(); 76 | Prepr pp = new Prepr( opts, reporter, incSearch.finish( opts ), 77 | fileName, new FileInputStream( fileName ), symTable ); 78 | BisonLexer lex = new BisonLexer(reporter, symTable, pp); 79 | CParser parser = new CParser( 80 | lex, 81 | new CompEnv( opts, reporter, new OurVisitor(new PrintWriter(System.out))), symTable 82 | ); 83 | parser.setDebugLevel( debugLevel ); 84 | parser.parse(); 85 | } 86 | catch (Exception e) 87 | { 88 | e.printStackTrace(); 89 | } 90 | } 91 | 92 | private static final class OurVisitor implements Visitor.TranslationUnit 93 | { 94 | private final PrintWriter m_out; 95 | private int m_indent; 96 | 97 | private OurVisitor ( PrintWriter out ) 98 | { 99 | m_out = out; 100 | } 101 | 102 | @Override 103 | public void visitRecordDecl ( TSpecTagNode specNode, Decl decl, boolean definition ) 104 | { 105 | m_out.format( "RecordDecl <%s> %s%s\n", SourceRange.formatRange(decl), decl.type.readableType(), 106 | definition ? " definition" : " forward ref"); 107 | if (definition) 108 | { 109 | m_indent += 2; 110 | Types.StructUnionSpec agg = (Types.StructUnionSpec) decl.type.spec; 111 | for (Types.Member m : agg.getFields()) 112 | visitField( agg, m ); 113 | m_indent -= 2; 114 | } 115 | m_out.flush(); 116 | } 117 | 118 | private void visitField ( Types.StructUnionSpec agg, Types.Member m ) 119 | { 120 | ExprFormatter.printIndent( m_indent, m_out ); 121 | m_out.format( "FieldDecl <%s> %s: %s\n", SourceRange.formatRange(m), m.name.name, m.type.readableType() ); 122 | } 123 | 124 | @Override 125 | public Visitor.DeclaratorList visitDeclaratorList ( TSpecNode specNode ) 126 | { 127 | return new Visitor.DeclaratorList() 128 | { 129 | @Override 130 | public void visitDeclaration ( TDeclaration tDecl, Decl decl ) 131 | { 132 | m_out.format( "Decl <%s> %s %s %s: %s\n", SourceRange.formatRange(decl), 133 | decl.sclass, decl.linkage, decl.symbol.name, 134 | decl.type.readableType() ); 135 | } 136 | 137 | @Override 138 | public void visitEmptyDeclaration ( TDeclaration tDecl ) 139 | { 140 | if (false) 141 | { 142 | m_out.format( "EmptyDecl <%s> %s %s: %s\n", SourceRange.formatRange(tDecl), 143 | tDecl.sclass, tDecl.linkage, tDecl.type.readableType() ); 144 | } 145 | } 146 | 147 | @Override public void end () 148 | { 149 | m_out.flush(); 150 | } 151 | }; 152 | } 153 | } 154 | 155 | 156 | } 157 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/.gitignore: -------------------------------------------------------------------------------- 1 | CParser.java 2 | 3 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/AstActions.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.Constant; 4 | import c99.Utils; 5 | import c99.parser.ast.*; 6 | 7 | public class AstActions extends BaseActions 8 | { 9 | 10 | public final Ast ast ( Code code ) 11 | { 12 | return new Ast0( code.name() ).value(code); 13 | } 14 | 15 | public final Ast ast ( Code code, CParser.Location loc ) 16 | { 17 | return new Ast0( code.name() ).value(code).location(loc); 18 | } 19 | 20 | public final Ast ast ( Code code, Ast a ) 21 | { 22 | return new Ast1( code.name(), a ).value(code); 23 | } 24 | 25 | public final Ast ast ( Code code, Ast a, Ast b ) 26 | { 27 | return new Ast2( code.name(), a, b ).value(code); 28 | } 29 | 30 | public final Ast ast ( String name ) 31 | { 32 | return new Ast0( name ); 33 | } 34 | 35 | public final Ast ast ( String name, Ast a ) 36 | { 37 | return new Ast1( name, a ); 38 | } 39 | 40 | public final Ast ast ( String name, Ast a, Ast b ) 41 | { 42 | return new Ast2( name, a, b ); 43 | } 44 | 45 | public final Ast ast ( String name, Ast a, Ast b, Ast c ) 46 | { 47 | return new Ast3( name, a, b, c ); 48 | } 49 | 50 | public final Ast ast ( String name, Ast a, Ast b, Ast c, Ast d ) 51 | { 52 | return new Ast4( name, a, b, c, d ); 53 | } 54 | 55 | public final Ast astAppend ( Ast t, Ast newChild ) 56 | { 57 | final int chCount = t.childCount(); 58 | switch (chCount) 59 | { 60 | case 0: return new Ast1( t.name, newChild ); 61 | case 1: return new Ast2( t.name, t.child( 0 ), newChild ); 62 | case 2: return new Ast3( t.name, t.child( 0 ), t.child( 1 ), newChild ); 63 | case 3: return new Ast4( t.name, t.child( 0 ), t.child( 1 ), t.child( 2 ), newChild ); 64 | default: 65 | Ast[] children = new Ast[chCount + 1]; 66 | for ( int i = 0; i < chCount; ++i ) 67 | children[i] = t.child( i ); 68 | children[chCount] = newChild; 69 | return new AstN( t.name, children ); 70 | } 71 | } 72 | 73 | public final Ast leftAppend ( Ast newChild, Ast t ) 74 | { 75 | final int chCount = t.childCount(); 76 | switch (chCount) 77 | { 78 | case 0: return new Ast1( t.name, newChild ).value(t.value); 79 | case 1: return new Ast2( t.name, newChild, t.child( 0 ) ).value(t.value); 80 | case 2: return new Ast3( t.name, newChild, t.child( 0 ), t.child( 1 ) ).value(t.value); 81 | case 3: return new Ast4( t.name, newChild, t.child( 0 ), t.child( 1 ), t.child( 2 ) ).value(t.value); 82 | default: 83 | Ast[] children = new Ast[chCount + 1]; 84 | for ( int i = 0; i < chCount; ++i ) 85 | children[i+1] = t.child( i ); 86 | children[0] = newChild; 87 | return new AstN( t.name, children ).value(t.value); 88 | } 89 | } 90 | 91 | public final Ast constant ( Constant.ArithC v, CParser.Location loc ) 92 | { 93 | return new Ast0( "const:"+ v.toString() ).value(v).location( loc ); 94 | } 95 | 96 | public final Ast seqAppend ( Ast seq, Ast newNode ) 97 | { 98 | if (seq == null) 99 | return newNode; 100 | if (newNode == null) 101 | return seq; 102 | 103 | Ast cur = seq, ch; 104 | int ind; 105 | while ( (ch = cur.child(ind = cur.childCount()-1)) != null) 106 | cur = ch; 107 | cur.setChild( ind, newNode ); 108 | return seq; 109 | } 110 | 111 | public void print ( Ast t ) 112 | { 113 | if (t != null) 114 | t.print( 0, System.out, 100 ); 115 | } 116 | 117 | } // class 118 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/BaseActions.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.*; 4 | import c99.Types.*; 5 | 6 | public class BaseActions 7 | { 8 | protected CompEnv m_compEnv; 9 | protected SymTable m_symTab; 10 | protected Platform m_plat; 11 | 12 | protected CompilerOptions m_opts; 13 | protected IErrorReporter m_reporter; 14 | 15 | private Types.SimpleSpec m_specs[]; 16 | private Qual m_stdQuals[]; 17 | 18 | protected Spec stdSpec ( TypeSpec ts ) 19 | { 20 | return m_specs[ts.ordinal() - TypeSpec.VOID.ordinal()]; 21 | } 22 | protected Qual stdQual ( TypeSpec ts ) 23 | { 24 | return m_stdQuals[ts.ordinal() - TypeSpec.VOID.ordinal()]; 25 | } 26 | 27 | private static final SimpleSpec s_errorSpec = new SimpleSpec( TypeSpec.ERROR, -1, 0 ); 28 | protected static final Qual s_errorQual = new Qual(s_errorSpec); 29 | 30 | protected void init ( CompEnv compEnv, SymTable symTab ) 31 | { 32 | m_compEnv = compEnv; 33 | m_symTab = symTab; 34 | m_plat = new Platform( m_compEnv ); 35 | 36 | m_opts = compEnv.opts; 37 | m_reporter = compEnv.reporter; 38 | 39 | // Initialize the basic type specs 40 | m_specs = new SimpleSpec[TypeSpec.LDOUBLE.ordinal() - TypeSpec.VOID.ordinal() + 1]; 41 | m_stdQuals = new Qual[m_specs.length]; 42 | for ( int i = TypeSpec.VOID.ordinal(); i <= TypeSpec.LDOUBLE.ordinal(); ++i ) 43 | { 44 | final TypeSpec type = TypeSpec.values()[i]; 45 | int size = -1, align = 0; 46 | if (type.sizeOf > 0) 47 | { 48 | size = type.sizeOf; 49 | align = m_plat.alignment( size ); 50 | } 51 | int ind = i - TypeSpec.VOID.ordinal(); 52 | m_specs[ind] = new SimpleSpec( type, size, align ); 53 | m_stdQuals[ind] = new Qual( m_specs[ind] ); 54 | } 55 | } 56 | 57 | public final void error ( CParser.Location loc, String msg, Object... args ) 58 | { 59 | m_reporter.error( BisonLexer.fromLocation( loc ), msg, args ); 60 | } 61 | 62 | public final void error ( ISourceRange rng, String msg, Object... args ) 63 | { 64 | m_reporter.error( rng, msg, args ); 65 | } 66 | 67 | public final void warning ( CParser.Location loc, String msg, Object... args ) 68 | { 69 | m_reporter.warning( BisonLexer.fromLocation( loc ), msg, args ); 70 | } 71 | 72 | public final void warning ( ISourceRange rng, String msg, Object... args ) 73 | { 74 | m_reporter.warning( rng, msg, args ); 75 | } 76 | 77 | public final void pedWarning ( CParser.Location loc, String msg, Object... args ) 78 | { 79 | warning( loc, msg, args ); 80 | } 81 | 82 | public final void extWarning ( CParser.Location loc, String msg, Object... args ) 83 | { 84 | warning( loc, msg, args ); 85 | } 86 | 87 | protected final PointerSpec newPointerSpec ( Qual to ) 88 | { 89 | int size = m_plat.pointerSize( to ); 90 | int align = m_plat.alignment( size ); 91 | return new PointerSpec( to, size, align ); 92 | } 93 | 94 | /** 95 | * 96 | * @param loc 97 | * @param to 98 | * @param nelem < 0 means not specified 99 | * @return 100 | */ 101 | protected final ArraySpec newArraySpec ( ISourceRange loc, Qual to, long nelem ) 102 | { 103 | assert to.spec.isComplete() && to.spec.sizeOf() >= 0; 104 | 105 | if (nelem >= 0) 106 | { 107 | // Check for int64 overflow 108 | if (nelem != 0 && to.spec.sizeOf() > (Long.MAX_VALUE / nelem)) 109 | { 110 | error( loc, "array size integer overflow" ); 111 | return null; 112 | } 113 | long size = (nelem * to.spec.sizeOf()) & Long.MAX_VALUE; // note: convert to unsigned 114 | 115 | if (size > TypeSpec.SIZE_T.maxValue) 116 | { 117 | error( loc, "array size doesn't fit in size_t" ); 118 | return null; 119 | } 120 | 121 | return new ArraySpec( to, nelem, size ); 122 | } 123 | else 124 | return new ArraySpec( to ); 125 | } 126 | } // class 127 | 128 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/BisonLexer.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.IErrorReporter; 4 | import c99.ISourceRange; 5 | import c99.SourceRange; 6 | import c99.Types; 7 | import c99.parser.pp.PPDefs; 8 | import c99.parser.pp.Prepr; 9 | 10 | import java.io.IOException; 11 | 12 | public final class BisonLexer implements CParser.Lexer 13 | { 14 | private final IErrorReporter m_reporter; 15 | private final SymTable m_symTab; 16 | private final Prepr m_prepr; 17 | 18 | private Object m_yylval; 19 | private Position m_startPos = new Position(); 20 | private Position m_endPos = new Position(); 21 | 22 | public BisonLexer ( final IErrorReporter reporter, final SymTable symTab, final Prepr prepr ) 23 | { 24 | m_reporter = reporter; 25 | m_symTab = symTab; 26 | m_prepr = prepr; 27 | 28 | initKeywords(); 29 | } 30 | 31 | private final void initKeywords () 32 | { 33 | for ( int i = Code.FIRST_KW.ordinal(); i <= Code.LAST_KW.ordinal(); ++i ) 34 | { 35 | final Code c = Code.values()[i]; 36 | m_symTab.symbol( c.str ).keyword = c; 37 | } 38 | } 39 | 40 | public final void close () 41 | { 42 | m_prepr.close(); 43 | } 44 | 45 | @Override 46 | public Position getStartPos () 47 | { 48 | return m_startPos; 49 | } 50 | 51 | @Override 52 | public Position getEndPos () 53 | { 54 | return m_endPos; 55 | } 56 | 57 | @Override 58 | public Object getLVal () 59 | { 60 | return m_yylval; 61 | } 62 | 63 | @Override 64 | public int yylex () throws IOException 65 | { 66 | for(;;) 67 | { 68 | PPDefs.Token ppt; 69 | do 70 | ppt = m_prepr.nextToken(); 71 | while (ppt.code() == Code.NEWLINE || ppt.code() == Code.WHITESPACE); 72 | 73 | m_startPos = new Position( ppt.fileName, ppt.line1, ppt.col1 ); 74 | m_endPos = new Position( ppt.fileName2 != null ? ppt.fileName2 : ppt.fileName, ppt.line2, ppt.col2 ); 75 | 76 | Code code = ppt.code(); 77 | //m_yylval = null; 78 | m_yylval = code; 79 | 80 | switch (code) 81 | { 82 | case IDENT: 83 | { 84 | Symbol sym = ppt.symbol(); 85 | Code kw = sym.keyword; 86 | if (kw != null) 87 | { 88 | code = kw; 89 | m_yylval = code; 90 | } 91 | else 92 | { 93 | if (sym.topDecl != null && sym.topDecl.sclass == Types.SClass.TYPEDEF) 94 | { 95 | code = Code.TYPENAME; 96 | m_yylval = sym.topDecl; 97 | } 98 | else 99 | m_yylval = sym; 100 | } 101 | } 102 | break; 103 | 104 | case EOF: 105 | return CParser.Lexer.EOF; 106 | 107 | case CHAR_CONST: 108 | code = Code.INT_NUMBER; 109 | m_yylval = ppt.getCharConstValue(); 110 | break; 111 | 112 | case INT_NUMBER: 113 | m_yylval = ppt.getIntConstValue(); 114 | break; 115 | 116 | case REAL_NUMBER: 117 | m_yylval = ppt.getRealConst(); 118 | break; 119 | 120 | case STRING_CONST: 121 | m_yylval = ppt.getStringConstValue(); 122 | break; 123 | 124 | case WIDE_CHAR_CONST: 125 | case WIDE_STRING_CONST: 126 | m_reporter.error( ppt, "Wide characters not supported" ); 127 | continue; 128 | 129 | default: 130 | int ord = ppt.code().ordinal(); 131 | if (ord >= Code.HASH.ordinal()) 132 | { 133 | m_reporter.error( ppt, "Unrecognized symbol '%s'", ppt.outputString() ); 134 | continue; 135 | } 136 | break; 137 | } 138 | 139 | return code.ordinal() + 257; 140 | } 141 | } 142 | 143 | public static T setLocation ( T rng, CParser.Location loc ) 144 | { 145 | rng.setRange( loc.begin.fileName, loc.begin.line, loc.begin.col, 146 | loc.end.fileName, loc.end.line, loc.end.col ); 147 | return rng; 148 | } 149 | 150 | public static SourceRange fromLocation ( CParser.Location loc ) 151 | { 152 | return setLocation( new SourceRange(), loc ); 153 | } 154 | 155 | public static CParser.Location toLocation ( ISourceRange rng ) 156 | { 157 | return new CParser.Location( 158 | new Position( rng.getFileName(), rng.getLine1(), rng.getCol1() ), 159 | new Position( rng.getFileName2(), rng.getLine2(), rng.getCol2() ) 160 | ); 161 | } 162 | 163 | @Override 164 | public void yyerror ( final CParser.Location loc, final String msg ) 165 | { 166 | m_reporter.error( fromLocation(loc), msg ); 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/Decl.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.Constant; 4 | import c99.ISourceRange; 5 | import c99.SourceRange; 6 | import c99.Types.*; 7 | 8 | public class Decl extends SourceRange 9 | { 10 | 11 | public static enum Kind 12 | { 13 | VAR, 14 | ENUM_CONST, 15 | TYPE, 16 | TAG, 17 | } 18 | public final Kind kind; 19 | Decl prev; 20 | public final Decl importedDecl; 21 | public final Scope scope; 22 | public SClass sclass; 23 | public final Linkage linkage; 24 | public final Symbol symbol; 25 | public Qual type; 26 | public Constant.IntC enumValue; 27 | public int bitfieldWidth = -1; //< -1 means not a bit-field 28 | public boolean defined; 29 | public boolean error; 30 | 31 | 32 | public Decl ( 33 | ISourceRange rng, Kind kind, Scope scope, SClass sclass, Linkage linkage, Symbol symbol, Qual type, 34 | boolean defined, boolean error 35 | ) 36 | { 37 | super(rng); 38 | this.importedDecl = null; 39 | this.kind = kind; 40 | this.scope = scope; 41 | this.sclass = sclass; 42 | this.linkage = linkage; 43 | this.symbol = symbol; 44 | this.type = type; 45 | this.defined = defined; 46 | this.error = error || type.spec.isError(); 47 | } 48 | 49 | /** Import a declaration into the current scope */ 50 | public Decl ( ISourceRange rng, Scope scope, Decl importedDecl, boolean error ) 51 | { 52 | super(rng); 53 | assert importedDecl.scope != scope; 54 | assert importedDecl.importedDecl == null; 55 | 56 | this.importedDecl = importedDecl; 57 | this.kind = importedDecl.kind; 58 | this.scope = scope; 59 | this.sclass = importedDecl.sclass; 60 | this.linkage = importedDecl.linkage; 61 | this.symbol = importedDecl.symbol; 62 | this.type = importedDecl.type; 63 | this.defined = importedDecl.defined; 64 | this.error = importedDecl.error | error; 65 | } 66 | 67 | public final void orError ( boolean f ) 68 | { 69 | this.error |= f; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/EnumConstDecl.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.Constant; 4 | import c99.ISourceRange; 5 | import c99.Types; 6 | 7 | public class EnumConstDecl extends Decl 8 | { 9 | public final Constant.IntC value; 10 | 11 | public EnumConstDecl ( 12 | ISourceRange rng, Scope scope, Symbol symbol, Types.Qual type, Constant.IntC value, boolean error 13 | ) 14 | { 15 | super( rng, Kind.ENUM_CONST, scope, Types.SClass.NONE, Linkage.NONE, symbol, type, true, error ); 16 | this.value = value; 17 | } 18 | } // class 19 | 20 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/EnumScope.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.Constant; 4 | import c99.TypeSpec; 5 | 6 | public final class EnumScope extends Scope 7 | { 8 | public TypeSpec baseSpec; 9 | public Constant.IntC lastValue; 10 | 11 | public EnumScope ( Scope parent ) 12 | { 13 | super( Kind.ENUM, parent ); 14 | this.baseSpec = TypeSpec.SINT; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/Linkage.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | public enum Linkage 4 | { 5 | NONE, 6 | INTERNAL, 7 | EXTERNAL 8 | } 9 | 10 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ParamScope.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | public final class ParamScope extends Scope 4 | { 5 | private boolean m_ellipsis; 6 | 7 | public ParamScope ( Scope parent ) 8 | { 9 | super( Kind.PARAM, parent ); 10 | } 11 | 12 | public final boolean getEllipsis () 13 | { 14 | assert this.kind == Kind.PARAM; 15 | return m_ellipsis; 16 | } 17 | 18 | public final void setEllipsis () 19 | { 20 | assert this.kind == Kind.PARAM; 21 | m_ellipsis = true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ParserActions.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | public class ParserActions extends DeclActions 4 | { 5 | } // class 6 | 7 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/Position.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | public class Position 4 | { 5 | public final String fileName; 6 | public final int line, col; 7 | 8 | public Position ( final String fileName, final int line, final int col ) 9 | { 10 | this.fileName = fileName; 11 | this.line = line; 12 | this.col = col; 13 | } 14 | 15 | public Position () 16 | { 17 | this.fileName = null; 18 | this.line = this.col = 0; 19 | } 20 | 21 | @Override 22 | public boolean equals ( final Object o ) 23 | { 24 | if (this == o) 25 | { 26 | return true; 27 | } 28 | if (!(o instanceof Position)) 29 | { 30 | return false; 31 | } 32 | 33 | Position position = (Position)o; 34 | 35 | return col == position.col && line == position.line && 36 | !(fileName != null ? !fileName.equals( position.fileName ) : position.fileName != null); 37 | } 38 | 39 | @Override 40 | public int hashCode () 41 | { 42 | int result = fileName != null ? fileName.hashCode() : 0; 43 | result = 31 * result + line; 44 | result = 31 * result + col; 45 | return result; 46 | } 47 | 48 | @Override 49 | public String toString () 50 | { 51 | return fileName + '(' + line + ")[" + col + ']'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/Scope.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import java.util.Collection; 4 | import java.util.LinkedList; 5 | 6 | public class Scope 7 | { 8 | public static enum Kind { FILE, BLOCK, PARAM, AGGREGATE, ENUM } 9 | 10 | public final Kind kind; 11 | private final Scope m_parent; 12 | private final LinkedList m_decls = new LinkedList(); 13 | private final LinkedList m_tags = new LinkedList(); 14 | 15 | private boolean m_error; 16 | 17 | public Scope ( Kind kind, final Scope parent ) 18 | { 19 | this.kind = kind; 20 | m_parent = parent; 21 | } 22 | 23 | public final Scope getParent () 24 | { 25 | return m_parent; 26 | } 27 | 28 | public final void orError ( boolean err ) 29 | { 30 | m_error |= err; 31 | } 32 | 33 | public boolean isError () 34 | { 35 | return m_error; 36 | } 37 | 38 | public final void pushDecl ( Decl decl ) 39 | { 40 | orError( decl.error ); 41 | m_decls.add( decl ); 42 | 43 | assert decl.prev == null; 44 | if (decl.symbol != null) 45 | { 46 | assert decl.symbol.topDecl == null || decl.symbol.topDecl.scope != decl.scope; 47 | 48 | decl.prev = decl.symbol.topDecl; 49 | decl.symbol.topDecl = decl; 50 | } 51 | } 52 | 53 | public final void pushTag ( Decl decl ) 54 | { 55 | orError( decl.error ); 56 | m_tags.add( decl ); 57 | 58 | assert decl.prev == null; 59 | if (decl.symbol != null) 60 | { 61 | assert decl.symbol.topTag == null || decl.symbol.topTag.scope != decl.scope; 62 | 63 | decl.prev = decl.symbol.topTag; 64 | decl.symbol.topTag = decl; 65 | } 66 | } 67 | 68 | public final void pop () 69 | { 70 | for ( Decl d : m_decls ) 71 | if (d.symbol != null) 72 | { 73 | assert d.symbol.topDecl == d; 74 | d.symbol.topDecl = d.prev; 75 | d.prev = null; 76 | } 77 | for ( Decl d : m_tags ) 78 | if (d.symbol != null) 79 | { 80 | assert d.symbol.topTag == d; 81 | d.symbol.topTag = d.prev; 82 | d.prev = null; 83 | } 84 | } 85 | 86 | public final Collection decls () 87 | { 88 | return m_decls; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/SymTable.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | public class SymTable extends IdentTable 4 | { 5 | @Override 6 | protected Symbol newIdent ( byte[] bytes, int hash ) 7 | { 8 | return new Symbol( bytes, hash ); 9 | } 10 | 11 | } // class 12 | 13 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/Symbol.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.parser.pp.PPSymbol; 4 | 5 | public class Symbol extends PPSymbol 6 | { 7 | public Code keyword; 8 | 9 | public Decl topDecl; 10 | public Decl topTag; 11 | public Object label; 12 | 13 | public Symbol ( byte bytes[], int hash ) 14 | { 15 | super(bytes, hash); 16 | } 17 | } // class 18 | 19 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/TreeActions.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.Constant; 4 | import c99.parser.tree.TIdent; 5 | import c99.parser.tree.TStringLiteral; 6 | 7 | 8 | public class TreeActions extends AstActions 9 | { 10 | 11 | public TStringLiteral stringLiteral ( CParser.Location loc, byte[] value ) 12 | { 13 | return BisonLexer.setLocation(new TStringLiteral(null,value), loc); 14 | } 15 | 16 | public TStringLiteral stringLiteral ( CParser.Location loc, TStringLiteral lit, byte[] value ) 17 | { 18 | // Combine the two strings 19 | final byte[] comb = new byte[lit.value.length + value.length]; 20 | System.arraycopy( lit.value, 0, comb, 0, lit.value.length ); 21 | System.arraycopy( value, 0, comb, lit.value.length, value.length ); 22 | 23 | return BisonLexer.setLocation(new TStringLiteral(null,value), loc); 24 | } 25 | 26 | public TIdent symbolTree ( CParser.Location loc, Symbol sym ) 27 | { 28 | return BisonLexer.setLocation( new TIdent(null,sym), loc ); 29 | } 30 | 31 | public Trees.TIntNumber intNumber ( CParser.Location loc, Constant.IntC value ) 32 | { 33 | return BisonLexer.setLocation( new Trees.TIntNumber(null,value), loc ); 34 | } 35 | 36 | public Trees.TreeList treeList ( Trees.TreeList list, Trees.Tree elem ) 37 | { 38 | if (list == null) 39 | list = new Trees.TreeList(); 40 | list.add( elem ); 41 | return list; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/Trees.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.Constant; 4 | import c99.ExtAttr; 5 | import c99.ISourceRange; 6 | import c99.SourceRange; 7 | 8 | import java.util.ArrayList; 9 | 10 | @Deprecated 11 | public abstract class Trees 12 | { 13 | public static class Tree extends SourceRange 14 | { 15 | public Tree ( ISourceRange rng ) 16 | { 17 | super( rng ); 18 | } 19 | } // class 20 | 21 | public static class TreeList extends ArrayList 22 | { 23 | } 24 | 25 | public static class TExtAttr extends Tree 26 | { 27 | public final ExtAttr extAttr; 28 | 29 | public TExtAttr ( final ISourceRange rng, final ExtAttr extAttr ) 30 | { 31 | super(rng); 32 | this.extAttr = extAttr; 33 | } 34 | } 35 | 36 | public static class TExtAttrList extends ArrayList 37 | { 38 | } 39 | 40 | public static class TIntNumber extends Tree 41 | { 42 | public final Constant.IntC value; 43 | 44 | public TIntNumber ( final ISourceRange rng, final Constant.IntC value ) 45 | { 46 | super(rng); 47 | this.value = value; 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ast/Ast.java: -------------------------------------------------------------------------------- 1 | package c99.parser.ast; 2 | 3 | import c99.SourceRange; 4 | import c99.parser.BisonLexer; 5 | import c99.parser.CParser; 6 | 7 | import java.io.PrintStream; 8 | 9 | public abstract class Ast extends SourceRange 10 | { 11 | public final String name; 12 | public Object value; 13 | 14 | protected Ast ( final String name, final Object value ) 15 | { 16 | this.name = name; 17 | this.value = value; 18 | } 19 | 20 | protected Ast ( final String name ) 21 | { 22 | this( name, null ); 23 | } 24 | 25 | public Ast location ( CParser.Location loc ) 26 | { 27 | BisonLexer.setLocation( this, loc ); 28 | return this; 29 | } 30 | 31 | public Ast value ( Object value ) 32 | { 33 | this.value = value; 34 | return this; 35 | } 36 | 37 | public abstract int childCount (); 38 | public abstract Ast child ( int n ); 39 | public abstract void setChild ( int n, Ast ch ); 40 | 41 | @Override 42 | public String toString () 43 | { 44 | return this.name+'['+childCount()+']'; 45 | } 46 | 47 | static final String s_sp1 = " "; 48 | static final String s_sp2 = " "; 49 | public static void printIndent ( int indent, PrintStream out ) 50 | { 51 | for ( ; indent >= s_sp1.length(); indent -= s_sp1.length() ) 52 | out.print( s_sp1 ); 53 | for ( ; indent >= s_sp2.length(); indent -= s_sp2.length() ) 54 | out.print( s_sp2 ); 55 | while (--indent >= 0) 56 | out.print( ' ' ); 57 | } 58 | 59 | private static final int INDENT_STEP = 4; 60 | 61 | private static final Ast s_nullChild = new Ast(""){ 62 | @Override public int childCount () { return 0; } 63 | @Override public Ast child ( final int n ) { assert false; return null; } 64 | @Override public void setChild ( final int n, final Ast ch ) { assert false; } 65 | }; 66 | 67 | private final Ast getChild ( int n ) 68 | { 69 | Ast ch; 70 | if ((ch = child( n )) == null) 71 | ch = s_nullChild; 72 | return ch; 73 | } 74 | 75 | public final void print ( int indent, PrintStream out, int maxWidth ) 76 | { 77 | printIndent( indent, out ); 78 | 79 | int remWidth = maxWidth - indent; 80 | StringBuilder shortBuf = remWidth > 0 ? new StringBuilder( remWidth ) : null; 81 | 82 | if (shortBuf != null) 83 | { 84 | if (tryFormat( remWidth, shortBuf )) 85 | { 86 | out.println( shortBuf.toString() ); 87 | return; 88 | } 89 | } 90 | 91 | out.println( this.name ); 92 | 93 | final int chCount = childCount(); 94 | if (chCount == 0) 95 | return; 96 | 97 | indent += INDENT_STEP; 98 | remWidth -= INDENT_STEP; 99 | 100 | for ( int i = 0; i < chCount; ++i ) 101 | { 102 | final Ast ch = getChild( i ); 103 | 104 | if (remWidth > 0 && 105 | shortBuf != null /*redundant but helps verification*/) 106 | { 107 | shortBuf.setLength( 0 ); 108 | if (ch.tryFormat( remWidth, shortBuf )) 109 | { 110 | printIndent( indent, out ); 111 | out.println( shortBuf.toString() ); 112 | continue; 113 | } 114 | } 115 | 116 | ch.print( indent, out, remWidth ); 117 | } 118 | } 119 | 120 | public final boolean tryFormat ( int maxWidth, StringBuilder shortBuf ) 121 | { 122 | if (maxWidth <= 0) 123 | return false; 124 | 125 | final int chCount = childCount(); 126 | final int startLen = shortBuf.length(); 127 | int remWidth = maxWidth; 128 | 129 | if (chCount > 0) 130 | { 131 | if (--remWidth < 0) 132 | return false; 133 | shortBuf.append( '(' ); 134 | } 135 | 136 | if ( (remWidth -= this.name.length()) < 0) 137 | return false; 138 | shortBuf.append( this.name ); 139 | 140 | if (chCount > 0) 141 | { 142 | for ( int i = 0; i < chCount; ++i ) 143 | { 144 | if (--remWidth < 0) 145 | return false; 146 | shortBuf.append( ' ' ); 147 | 148 | if (!getChild( i ).tryFormat( remWidth, shortBuf )) 149 | return false; 150 | remWidth = maxWidth - shortBuf.length() + startLen; 151 | assert remWidth >= 0; 152 | } 153 | 154 | if (--remWidth < 0) 155 | return false; 156 | shortBuf.append( ')' ); 157 | } 158 | 159 | return true; 160 | } 161 | 162 | } // class 163 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ast/Ast0.java: -------------------------------------------------------------------------------- 1 | package c99.parser.ast; 2 | 3 | public class Ast0 extends Ast 4 | { 5 | public Ast0 ( final String name ) 6 | { 7 | super( name ); 8 | } 9 | 10 | @Override 11 | public int childCount () 12 | { 13 | return 0; 14 | } 15 | 16 | @Override 17 | public Ast child ( final int n ) 18 | { 19 | assert false; 20 | return null; 21 | } 22 | 23 | @Override 24 | public void setChild ( final int n, final Ast ch ) 25 | { 26 | assert false; 27 | } 28 | } // class 29 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ast/Ast1.java: -------------------------------------------------------------------------------- 1 | package c99.parser.ast; 2 | 3 | public class Ast1 extends Ast 4 | { 5 | private Ast a; 6 | 7 | public Ast1 ( final String name, final Ast a ) 8 | { 9 | super( name ); 10 | this.a = a; 11 | } 12 | 13 | @Override 14 | public int childCount () 15 | { 16 | return 1; 17 | } 18 | 19 | @Override 20 | public Ast child ( final int n ) 21 | { 22 | assert n == 0; 23 | return a; 24 | } 25 | 26 | @Override 27 | public void setChild ( final int n, final Ast ch ) 28 | { 29 | assert n == 0; 30 | this.a = ch; 31 | } 32 | } // class 33 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ast/Ast2.java: -------------------------------------------------------------------------------- 1 | package c99.parser.ast; 2 | 3 | public class Ast2 extends Ast 4 | { 5 | private Ast a, b; 6 | 7 | public Ast2 ( final String name, final Ast a, final Ast b ) 8 | { 9 | super( name ); 10 | this.a = a; 11 | this.b = b; 12 | } 13 | 14 | @Override 15 | public int childCount () 16 | { 17 | return 2; 18 | } 19 | 20 | @Override 21 | public Ast child ( final int n ) 22 | { 23 | switch (n) 24 | { 25 | case 0: return a; 26 | case 1: return b; 27 | } 28 | assert false; 29 | return null; 30 | } 31 | 32 | @Override 33 | public void setChild ( final int n, final Ast ch ) 34 | { 35 | switch (n) 36 | { 37 | case 0: this.a = ch; break; 38 | case 1: this.b = ch; break; 39 | default: assert false; 40 | } 41 | } 42 | } // class 43 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ast/Ast3.java: -------------------------------------------------------------------------------- 1 | package c99.parser.ast; 2 | 3 | public class Ast3 extends Ast 4 | { 5 | private Ast a, b, c; 6 | 7 | public Ast3 ( final String name, final Ast a, final Ast b, final Ast c ) 8 | { 9 | super( name ); 10 | this.a = a; 11 | this.b = b; 12 | this.c = c; 13 | } 14 | 15 | @Override 16 | public int childCount () 17 | { 18 | return 3; 19 | } 20 | 21 | @Override 22 | public Ast child ( final int n ) 23 | { 24 | switch (n) 25 | { 26 | case 0: return a; 27 | case 1: return b; 28 | case 2: return c; 29 | } 30 | assert false; 31 | return null; 32 | } 33 | 34 | @Override 35 | public void setChild ( final int n, final Ast ch ) 36 | { 37 | switch (n) 38 | { 39 | case 0: this.a = ch; break; 40 | case 1: this.b = ch; break; 41 | case 2: this.c = ch; break; 42 | default: assert false; 43 | } 44 | } 45 | } // class 46 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ast/Ast4.java: -------------------------------------------------------------------------------- 1 | package c99.parser.ast; 2 | 3 | public class Ast4 extends Ast 4 | { 5 | private Ast a, b, c, d; 6 | 7 | public Ast4 ( final String name, final Ast a, final Ast b, final Ast c, final Ast d ) 8 | { 9 | super( name ); 10 | this.a = a; 11 | this.b = b; 12 | this.c = c; 13 | this.d = d; 14 | } 15 | 16 | @Override 17 | public int childCount () 18 | { 19 | return 4; 20 | } 21 | 22 | @Override 23 | public Ast child ( final int n ) 24 | { 25 | switch (n) 26 | { 27 | case 0: return a; 28 | case 1: return b; 29 | case 2: return c; 30 | case 3: return d; 31 | } 32 | assert false; 33 | return null; 34 | } 35 | 36 | @Override 37 | public void setChild ( final int n, final Ast ch ) 38 | { 39 | switch (n) 40 | { 41 | case 0: this.a = ch; break; 42 | case 1: this.b = ch; break; 43 | case 2: this.c = ch; break; 44 | case 3: this.d = ch; break; 45 | default: assert false; 46 | } 47 | } 48 | } // class 49 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/ast/AstN.java: -------------------------------------------------------------------------------- 1 | package c99.parser.ast; 2 | 3 | public class AstN extends Ast 4 | { 5 | private final Ast ch[]; 6 | 7 | public AstN ( final String name, final Ast... ch ) 8 | { 9 | super( name ); 10 | this.ch = ch; 11 | } 12 | 13 | @Override 14 | public int childCount () 15 | { 16 | return ch.length; 17 | } 18 | 19 | @Override 20 | public Ast child ( final int n ) 21 | { 22 | return ch[n]; 23 | } 24 | 25 | @Override 26 | public void setChild ( final int n, final Ast v ) 27 | { 28 | this.ch[n] = v; 29 | } 30 | } // class 31 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/ExprFormatter.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.SourceRange; 4 | 5 | import java.io.PrintWriter; 6 | 7 | public class ExprFormatter 8 | { 9 | private static final int INDENT_STEP = 4; 10 | 11 | static final String s_sp1 = " "; 12 | static final String s_sp2 = " "; 13 | 14 | public static void printIndent ( int indent, PrintWriter out ) 15 | { 16 | for ( ; indent >= s_sp1.length(); indent -= s_sp1.length() ) 17 | out.print( s_sp1 ); 18 | for ( ; indent >= s_sp2.length(); indent -= s_sp2.length() ) 19 | out.print( s_sp2 ); 20 | while (--indent >= 0) 21 | out.print( ' ' ); 22 | } 23 | 24 | public static void format ( int indent, PrintWriter out, TExpr.Expr e ) 25 | { 26 | printIndent( indent, out ); 27 | String details = e.formatDetails(); 28 | out.format( "%s:'%s'%s <%s>\n", e.getCode().name(), e.getQual().readableType(), 29 | details, SourceRange.formatRange(e) ); 30 | for ( int i = 0, c = e.getNumChildren(); i < c; ++i ) 31 | format( indent + INDENT_STEP, out, e.getChild( i ) ); 32 | out.flush(); 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TDeclSpec.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ExtAttributes; 4 | import c99.Types; 5 | 6 | /** 7 | * Created by tmikov on 1/5/15. 8 | */ 9 | public final class TDeclSpec 10 | { 11 | public Types.SClass sc; 12 | public final ExtAttributes scAttr; 13 | public final Types.Qual qual; 14 | public TSpecNode scNode; 15 | public TSpecNode thread; 16 | public TSpecNode inline; 17 | public TSpecNode noreturn; 18 | public boolean error; 19 | 20 | public TDeclSpec ( Types.SClass sc, ExtAttributes scAttr, final Types.Qual qual ) 21 | { 22 | this.sc = sc; 23 | this.scAttr = scAttr; 24 | this.qual = qual; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TDeclaration.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ISourceRange; 4 | import c99.SourceRange; 5 | import c99.Types; 6 | import c99.parser.*; 7 | 8 | /** 9 | * We need to accumulate parameter declarations because of reduce/reduce conflicts 10 | * in the grammar. That where we store each declaration. Then, for consistency, 11 | * we use the same object for all declarations, even if we consume it immediately. 12 | */ 13 | public final class TDeclaration extends SourceRange 14 | { 15 | public final TSpecNode dsNode; 16 | public final TDeclarator declarator; 17 | public TDeclSpec ds; 18 | 19 | public Types.SClass sclass; 20 | public Linkage linkage; 21 | public Types.Qual type; 22 | public boolean defined; 23 | public boolean error; 24 | 25 | public TDeclaration ( ISourceRange rng, TSpecNode dsNode, TDeclarator declarator ) 26 | { 27 | super(rng); 28 | this.dsNode = dsNode; 29 | this.declarator = declarator; 30 | } 31 | 32 | public TDeclaration ( CParser.Location loc, TSpecNode dsNode, TDeclarator declarator ) 33 | { 34 | this((ISourceRange)null, dsNode, declarator ); 35 | BisonLexer.setLocation( this, loc ); 36 | } 37 | 38 | public final boolean hasIdent () 39 | { 40 | return this.declarator.ident != null; 41 | } 42 | 43 | public final Symbol getIdent () 44 | { 45 | return this.declarator.ident; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TDeclarator.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ISourceRange; 4 | import c99.SourceRange; 5 | import c99.parser.*; 6 | 7 | /** 8 | * Created by tmikov on 1/5/15. 9 | */ 10 | public final class TDeclarator extends SourceRange 11 | { 12 | public final Symbol ident; 13 | Elem top; 14 | Elem bottom; 15 | 16 | public TDeclarator ( ISourceRange rng, final Symbol ident ) 17 | { 18 | super( rng ); 19 | this.ident = ident; 20 | } 21 | 22 | public TDeclarator append ( Elem next ) 23 | { 24 | if (next != null) 25 | { 26 | if (bottom != null) 27 | bottom.append( next ); 28 | else 29 | top = next; 30 | bottom = next; 31 | } 32 | return this; 33 | } 34 | 35 | public static interface Visitor 36 | { 37 | public boolean pointer ( int depth, PointerElem elem ); 38 | public boolean array ( int depth, ArrayElem elem ); 39 | public boolean function ( int depth, FuncElem elem ); 40 | } 41 | 42 | public boolean visitPost ( Visitor v ) 43 | { 44 | return this.top == null || visitHelper( 1, this.top, v ); 45 | } 46 | 47 | // FIXME: prevent unbound recursion. Limit the depth of the type chain 48 | private boolean visitHelper ( int depth, Elem elem, Visitor v ) 49 | { 50 | if (elem.to != null) 51 | if (!visitHelper( depth+1, elem.to, v )) 52 | return false; 53 | 54 | switch (elem.code) 55 | { 56 | case ASTERISK: return v.pointer( depth, (PointerElem)elem ); 57 | case L_BRACKET: return v.array( depth, (ArrayElem)elem ); 58 | case L_PAREN: return v.function( depth, (FuncElem)elem ); 59 | default: 60 | assert false : "Invalid type code " + elem.code; 61 | } 62 | return false; 63 | } 64 | 65 | /** 66 | * Created by tmikov on 1/5/15. 67 | */ 68 | public static abstract class Elem extends SourceRange 69 | { 70 | public final Code code; 71 | public Elem to; 72 | 73 | public Elem ( CParser.Location loc, Code code ) 74 | { 75 | this.code = code; 76 | BisonLexer.setLocation( this, loc ); 77 | } 78 | 79 | public Elem append ( Elem next ) 80 | { 81 | if (next != null) 82 | { 83 | assert this.to == null; 84 | this.to = next; 85 | } 86 | return this; 87 | } 88 | } 89 | 90 | public static final class PointerElem extends Elem 91 | { 92 | public final TSpecNode qualList; 93 | 94 | public PointerElem ( CParser.Location loc, TSpecNode qualList ) 95 | { 96 | super( loc, Code.ASTERISK ); 97 | this.qualList = qualList; 98 | } 99 | } 100 | 101 | public static final class ArrayElem extends Elem 102 | { 103 | public TSpecNode qualList; 104 | public SourceRange _static; 105 | public SourceRange asterisk; 106 | public SourceRange nelemLoc; 107 | public final TExpr.Expr nelem; 108 | 109 | public ArrayElem ( 110 | CParser.Location loc, TSpecNode qualList, CParser.Location _static, CParser.Location asterisk, 111 | CParser.Location nelemLoc, TExpr.Expr nelem 112 | ) 113 | { 114 | super( loc, Code.L_BRACKET ); 115 | this.qualList = qualList; 116 | this._static = _static == null ? null : BisonLexer.fromLocation( _static ); 117 | this.asterisk = asterisk == null ? null : BisonLexer.fromLocation( asterisk ); 118 | this.nelemLoc = nelemLoc == null ? null : BisonLexer.fromLocation( nelemLoc ); 119 | this.nelem = nelem; 120 | } 121 | } 122 | 123 | public static final class FuncElem extends Elem 124 | { 125 | public final ParamScope paramScope; 126 | public final TIdentList identList; 127 | 128 | public FuncElem ( CParser.Location loc, ParamScope paramScope, TIdentList identList ) 129 | { 130 | super( loc, Code.L_PAREN ); 131 | this.paramScope = paramScope; 132 | this.identList = identList; 133 | } 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TIdent.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ISourceRange; 4 | import c99.SourceRange; 5 | import c99.parser.Symbol; 6 | 7 | /** 8 | * Created by tmikov on 1/8/15. 9 | */ 10 | public class TIdent extends SourceRange 11 | { 12 | public final Symbol ident; 13 | 14 | public TIdent ( ISourceRange rng, Symbol ident ) 15 | { 16 | super( rng ); 17 | this.ident = ident; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TIdentList.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.Types; 4 | import c99.parser.Symbol; 5 | 6 | import java.util.LinkedHashMap; 7 | 8 | /** This class needed only as a workaround for a Bison BUG - generics in %type */ 9 | public final class TIdentList extends LinkedHashMap 10 | { 11 | } 12 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TSpecAttrNode.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ISourceRange; 4 | import c99.parser.Code; 5 | import c99.parser.Trees; 6 | 7 | /** 8 | * Created by tmikov on 1/5/15. 9 | */ 10 | public final class TSpecAttrNode extends TSpecNode 11 | { 12 | public final Trees.TExtAttrList attrList; 13 | 14 | public TSpecAttrNode ( final ISourceRange rgn, final Trees.TExtAttrList attrList ) 15 | { 16 | super(rgn, Code.GCC_ATTRIBUTE); 17 | this.attrList = attrList; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TSpecDeclNode.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ISourceRange; 4 | import c99.parser.Code; 5 | import c99.parser.Decl; 6 | 7 | /** 8 | * Created by tmikov on 1/5/15. 9 | */ 10 | public final class TSpecDeclNode extends TSpecNode 11 | { 12 | public final Decl decl; 13 | 14 | public TSpecDeclNode ( ISourceRange rng, Code code, Decl decl ) 15 | { 16 | super( rng, code ); 17 | this.decl = decl; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TSpecNode.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ISourceRange; 4 | import c99.SourceRange; 5 | import c99.parser.Code; 6 | import c99.parser.DeclActions; 7 | 8 | /** 9 | * Created by tmikov on 1/5/15. 10 | */ 11 | public class TSpecNode extends SourceRange 12 | { 13 | public final Code code; 14 | public TSpecNode next; 15 | 16 | public TSpecNode ( ISourceRange rgn, Code code ) 17 | { 18 | super(rgn); 19 | this.code = code; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TSpecTagNode.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ISourceRange; 4 | import c99.Types; 5 | import c99.parser.Code; 6 | 7 | public class TSpecTagNode extends TSpecNode 8 | { 9 | public final Types.TagSpec spec; 10 | 11 | public TSpecTagNode ( ISourceRange rgn, Code code, Types.TagSpec spec ) 12 | { 13 | super( rgn, code ); 14 | this.spec = spec; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TStringLiteral.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.ISourceRange; 4 | import c99.SourceRange; 5 | 6 | /** 7 | * Untyped string literal. Expressions use {@link c99.parser.tree.TExpr.StringLiteral} instead 8 | */ 9 | public class TStringLiteral extends SourceRange 10 | { 11 | public final byte[] value; 12 | public TStringLiteral ( final ISourceRange rng, byte[] value ) 13 | { 14 | super(rng); 15 | this.value = value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/TreeCode.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | public enum TreeCode 4 | { 5 | ERROR(""), 6 | VARREF(""), 7 | ENUM_CONST(""), 8 | CONSTANT(""), 9 | STRING(""), 10 | SUBSCRIPT("[]"), 11 | CALL(""), 12 | DOT_MEMBER("."), 13 | PTR_MEMBER("->"), 14 | POST_INC("()++"), 15 | POST_DEC("()--"), 16 | ADDRESS("&"), 17 | INDIRECT("*"), 18 | U_PLUS("+"), 19 | U_MINUS("-"), 20 | BITWISE_NOT("~"), 21 | LOG_NEG("!"), 22 | PRE_INC("++()"), 23 | PRE_DEC("--()"), 24 | SIZEOF_EXPR("sizeof"), 25 | ALIGNOF_EXPR("_Alignof"), 26 | SIZEOF_TYPE("sizeof"), 27 | ALIGNOF_TYPE("_Alignof"), 28 | LABEL_ADDRESS("&&label"), 29 | IMPLICIT_CAST(""), 30 | IMPLICIT_LOAD(""), 31 | TYPECAST(""), 32 | MUL("*"), 33 | DIV("/"), 34 | REMAINDER("%"), 35 | ADD("+"), 36 | SUB("-"), 37 | LSHIFT("<<"), 38 | RSHIFT(">>"), 39 | LT("<"), 40 | GT(">"), 41 | LE("<="), 42 | GE(">="), 43 | EQ("=="), 44 | NE("!="), 45 | BITWISE_AND("&"), 46 | BITWISE_XOR("^"), 47 | BITWISE_OR("|"), 48 | LOG_AND("&&"), 49 | LOG_OR("||"), 50 | ASSIGN("="), 51 | ASSIGN_MUL("*="), 52 | ASSIGN_DIV("/="), 53 | ASSIGN_REM("%="), 54 | ASSIGN_ADD("+="), 55 | ASSIGN_SUB("-="), 56 | ASSIGN_LSHIFT("<<="), 57 | ASSIGN_RSHIFT(">>="), 58 | ASSIGN_BITWISE_AND("&="), 59 | ASSIGN_BITWISE_XOR("^="), 60 | ASSIGN_BITWISE_OR("|="), 61 | COMMA(","), 62 | TERNARY("?:"), 63 | ; 64 | 65 | public final String str; 66 | 67 | private TreeCode ( String str ) 68 | { 69 | this.str = str; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /java/c99j/src/c99/parser/tree/Visitor.java: -------------------------------------------------------------------------------- 1 | package c99.parser.tree; 2 | 3 | import c99.parser.Decl; 4 | 5 | public final class Visitor 6 | { 7 | private Visitor () {}; 8 | 9 | public static interface TranslationUnit 10 | { 11 | public void visitRecordDecl ( TSpecTagNode specNode, Decl decl, boolean definition ); 12 | public DeclaratorList visitDeclaratorList ( TSpecNode specNode ); 13 | } 14 | 15 | public static interface DeclaratorList 16 | { 17 | public void visitDeclaration ( TDeclaration tDecl, Decl decl ); 18 | public void visitEmptyDeclaration ( TDeclaration tDecl ); 19 | public void end (); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /java/c99j/y/.gitignore: -------------------------------------------------------------------------------- 1 | CParser.xml 2 | CParser.html 3 | CParser.y 4 | 5 | 6 | -------------------------------------------------------------------------------- /java/c99j/y/defs.m4: -------------------------------------------------------------------------------- 1 | m4_divert(-1)m4_dnl 2 | m4_define(`dnl',`m4_dnl') 3 | 4 | m4_define(`_PUSH0',`{ yyval = $0; }') 5 | 6 | m4_define(`rule',`dnl 7 | m4_ifelse(`$1',`',``'',`m4_divert(1)%type$1 $2`'m4_ifelse($3,`opt',` $2_opt') 8 | m4_divert(2)')dnl 9 | m4_ifelse($3,`opt',`$2_opt: %empty { $$ = null; } | $2; ',$3,`optn',`$2_opt: %empty | $2; ')dnl 10 | $2') 11 | 12 | m4_define(`start_grammar',`m4_divert(2)') 13 | 14 | 15 | m4_define(`end_grammar',` 16 | m4_divert(0) 17 | m4_undivert(1) 18 | m4_undivert(2)') 19 | m4_divert`'dnl 20 | -------------------------------------------------------------------------------- /java/c99j/y/fix.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | 4 | int yylex ( void ); 5 | void yyerror ( const char * msg ); 6 | 7 | #define YYERROR_VERBOSE 1 8 | %} 9 | 10 | %token VOID INT CONST IDENT STATIC 11 | %token SEMI ";" 12 | %token LPAR "(" 13 | %token RPAR ")" 14 | %token ASTERISK "*" 15 | %% 16 | 17 | // (6.9) 18 | translation-unit: 19 | %empty 20 | | translation-unit external-declaration 21 | ; 22 | 23 | // (6.9) 24 | external-declaration: 25 | function-definition 26 | | declaration 27 | ; 28 | 29 | // (6.9.1) 30 | function-definition: 31 | declaration-specifiers declarator-func declaration-list_opt compound-statement 32 | ; 33 | 34 | compound-statement: 35 | "{" "}" 36 | ; 37 | 38 | // (6.9.1) 39 | declaration-list: 40 | declaration 41 | | declaration-list declaration 42 | ; 43 | 44 | declaration-list_opt: 45 | %empty 46 | | declaration-list 47 | ; 48 | 49 | 50 | declaration: 51 | declaration-specifiers init-declarator-list_opt ";" 52 | ; 53 | 54 | // deliberate right recursion here 55 | declaration-specifiers: 56 | specifier 57 | | specifier declaration-specifiers 58 | ; 59 | 60 | specifier: 61 | type-specifier 62 | | type-qualifier 63 | ; 64 | 65 | type-specifier: 66 | VOID 67 | | INT 68 | ; 69 | 70 | init-declarator-list: 71 | init-declarator 72 | | init-declarator-list "," init-declarator 73 | ; 74 | 75 | init-declarator-list_opt: 76 | %empty 77 | | init-declarator-list 78 | ; 79 | 80 | // (6.7) 81 | init-declarator: 82 | declarator 83 | ; 84 | 85 | 86 | // (6.7.6) 87 | declarator: 88 | declarator-func 89 | | declarator-nofunc 90 | ; 91 | 92 | declarator-func: 93 | pointer_opt direct-declarator-func 94 | ; 95 | 96 | declarator-nofunc: 97 | pointer_opt direct-declarator-nofunc 98 | ; 99 | 100 | pointer: 101 | "*" type-qualifier-list_opt 102 | | pointer "*" type-qualifier-list_opt 103 | ; 104 | 105 | pointer_opt: 106 | %empty 107 | | pointer 108 | ; 109 | 110 | // (6.7.6) 111 | type-qualifier-list: 112 | type-qualifier 113 | | type-qualifier-list type-qualifier 114 | ; 115 | 116 | type-qualifier-list_opt: 117 | %empty 118 | | type-qualifier-list 119 | ; 120 | 121 | 122 | // (6.7.3) 123 | type-qualifier: 124 | CONST 125 | ; 126 | 127 | // (6.7.6) 128 | 129 | // Parenthesized idenitifier 130 | pident: 131 | IDENT 132 | | "(" pident ")" 133 | ; 134 | 135 | direct-declarator: 136 | direct-declarator-func 137 | | direct-declarator-nofunc 138 | ; 139 | 140 | direct-declarator-func: 141 | pident elem-func 142 | | "(" direct-declarator-func ")" 143 | | direct-declarator-func direct-declarator-elem 144 | ; 145 | 146 | direct-declarator-nofunc: 147 | pident 148 | | d2 149 | ; 150 | 151 | d2: 152 | pident elem-nofunc 153 | | "(" pointer direct-declarator ")" 154 | | d2 direct-declarator-elem 155 | ; 156 | 157 | direct-declarator-elem: 158 | elem-nofunc 159 | | elem-func 160 | ; 161 | 162 | elem-nofunc: 163 | "[" type-qualifier-list_opt assignment-expression_opt "]" 164 | | "[" STATIC type-qualifier-list_opt assignment-expression "]" 165 | | "[" type-qualifier-list STATIC assignment-expression "]" 166 | | "[" type-qualifier-list_opt ASTERISK "]" 167 | ; 168 | 169 | elem-func: 170 | "(" parameter-type-list ")" 171 | | "(" identifier-list_opt ")" 172 | ; 173 | 174 | abstract-declarator: 175 | pointer 176 | | direct-abstract-declarator 177 | | pointer direct-abstract-declarator 178 | ; 179 | 180 | /*abstract-declarator_opt: 181 | %empty { $$ = null; } 182 | | abstract-declarator 183 | ;*/ 184 | 185 | // (6.7.7) 186 | direct-abstract-declarator: 187 | "(" abstract-declarator ")" 188 | | direct-abstract-declarator-elem 189 | | direct-abstract-declarator direct-abstract-declarator-elem 190 | ; 191 | 192 | direct-abstract-declarator-elem: 193 | "[" type-qualifier-list assignment-expression_opt "]" 194 | | "[" assignment-expression_opt "]" 195 | | "[" STATIC type-qualifier-list_opt assignment-expression "]" 196 | | "[" type-qualifier-list STATIC assignment-expression "]" 197 | | "[" ASTERISK "]" 198 | | "(" parameter-type-list ")" 199 | | "(" ")" 200 | ; 201 | 202 | // (6.7.6) 203 | parameter-type-list: 204 | parameter-list 205 | | parameter-list "," "..." 206 | ; 207 | 208 | // (6.7.6) 209 | parameter-list: 210 | parameter-declaration 211 | | parameter-list "," parameter-declaration 212 | ; 213 | 214 | // (6.7.6) 215 | parameter-declaration: 216 | declaration-specifiers 217 | | declaration-specifiers pointer 218 | | declaration-specifiers pointer direct-declarator 219 | | declaration-specifiers direct-declarator 220 | | declaration-specifiers pointer direct-abstract-declarator 221 | | declaration-specifiers direct-abstract-declarator 222 | ; 223 | 224 | // (6.7.6) 225 | identifier-list: 226 | IDENT 227 | | identifier-list "," IDENT 228 | ; 229 | 230 | identifier-list_opt: 231 | %empty 232 | | identifier-list 233 | ; 234 | 235 | assignment-expression: 236 | IDENT 237 | ; 238 | 239 | assignment-expression_opt: 240 | %empty 241 | | assignment-expression 242 | ; 243 | %% 244 | 245 | int yylex ( void ) 246 | { 247 | static int toks[] = { 248 | // int (*a)(void); 249 | INT, LPAR, ASTERISK, IDENT, RPAR, LPAR, VOID, RPAR, SEMI, 250 | // int (a)(int x); 251 | INT, LPAR, IDENT, RPAR, LPAR, INT, IDENT, RPAR, SEMI, 252 | // void (*signal(int sig))(int) 253 | VOID, LPAR, ASTERISK, IDENT, LPAR, INT, IDENT, RPAR, RPAR, LPAR, INT, RPAR, SEMI, 254 | // int (func) ( void ) (void) 255 | INT, LPAR, IDENT, RPAR, LPAR, VOID, RPAR, LPAR, VOID, RPAR, SEMI 256 | }; 257 | static int i = 0; 258 | 259 | return i < sizeof(toks)/sizeof(toks[0]) ? toks[i++] : EOF; 260 | } 261 | 262 | void yyerror ( const char * err ) 263 | { 264 | fprintf( stderr, "error: %s\n", err ); 265 | } 266 | 267 | int main ( void ) 268 | { 269 | return yyparse(); 270 | } 271 | -------------------------------------------------------------------------------- /java/cpp/cpp.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /java/cpp/src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: c99.driver.Preprocessor 3 | -------------------------------------------------------------------------------- /java/cpp/src/c99/DummyErrorReporter.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public class DummyErrorReporter implements IErrorReporter 4 | { 5 | 6 | public String formatRange ( ISourceRange rng ) 7 | { 8 | return SourceRange.formatRange( rng ); 9 | } 10 | 11 | private void print ( String severity, final ISourceRange rng, final String format, final Object... args ) 12 | { 13 | if (rng != null) 14 | System.err.format( "%s: %s: ", formatRange( rng ), severity ); 15 | else 16 | System.err.format( "%s: ", severity ); 17 | 18 | System.err.format( format, args ); 19 | System.err.println(); 20 | } 21 | 22 | @Override 23 | public void warning ( final ISourceRange rng, final String format, final Object... args ) 24 | { 25 | print( "warning", rng, format, args ); 26 | } 27 | 28 | @Override 29 | public void error ( final ISourceRange rng, final String format, final Object... args ) 30 | { 31 | print( "error", rng, format, args ); 32 | } 33 | } // class 34 | -------------------------------------------------------------------------------- /java/cpp/src/c99/FatalException.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public class FatalException extends RuntimeException 4 | { 5 | public FatalException () 6 | { 7 | } 8 | 9 | public FatalException ( final String message ) 10 | { 11 | super( message ); 12 | } 13 | 14 | public FatalException ( final String message, final Throwable cause ) 15 | { 16 | super( message, cause ); 17 | } 18 | 19 | public FatalException ( final Throwable cause ) 20 | { 21 | super( cause ); 22 | } 23 | } // class 24 | -------------------------------------------------------------------------------- /java/cpp/src/c99/IErrorReporter.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public interface IErrorReporter 4 | { 5 | public void warning ( ISourceRange rng, String format, Object... args ); 6 | public void error ( ISourceRange rng, String format, Object... args ); 7 | public String formatRange ( ISourceRange rng ); 8 | } 9 | -------------------------------------------------------------------------------- /java/cpp/src/c99/ILocation.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public interface ILocation 4 | { 5 | public String getFileName (); 6 | public int getLine (); 7 | public int getCol (); 8 | } 9 | -------------------------------------------------------------------------------- /java/cpp/src/c99/ISourceRange.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public interface ISourceRange 4 | { 5 | public String getFileName (); 6 | public int getLine1 (); 7 | public int getCol1 (); 8 | public String getFileName2 (); 9 | /** Inclusive */ 10 | public int getLine2 (); 11 | /** Exclusive */ 12 | public int getCol2 (); 13 | } 14 | -------------------------------------------------------------------------------- /java/cpp/src/c99/Ident.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public class Ident implements Comparable 4 | { 5 | public final byte[] bytes; 6 | public final String name; 7 | private final int m_hash; 8 | 9 | public Ident ( byte bytes[], int hash ) 10 | { 11 | this.bytes = bytes; 12 | this.name = Utils.asciiString( bytes, 0, bytes.length ); 13 | m_hash = hash; 14 | } 15 | 16 | public final int length () 17 | { 18 | return this.bytes.length; 19 | } 20 | 21 | @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") 22 | @Override 23 | public final boolean equals ( final Object o ) 24 | { 25 | return o == this; 26 | } 27 | 28 | @Override 29 | public final int hashCode () 30 | { 31 | return m_hash; 32 | } 33 | 34 | @Override 35 | public String toString () 36 | { 37 | return this.name; 38 | } 39 | 40 | public static int calcHashCode( byte val[], int off, int len ) 41 | { 42 | int h = 0; 43 | for (int i = 0; i < len; i++) { 44 | h = 31*h + (val[off++] & 0xFF); 45 | } 46 | return h; 47 | } 48 | 49 | @Override 50 | public final int compareTo ( Ident o ) 51 | { 52 | if (this == o) 53 | return 0; 54 | return m_hash < o.m_hash ? -1 : 55 | (m_hash > o.m_hash ? +1 : Utils.compare(this.bytes, 0, this.bytes.length, o.bytes, 0, o.bytes.length)); 56 | } 57 | } // class 58 | -------------------------------------------------------------------------------- /java/cpp/src/c99/Location.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | import c99.ILocation; 4 | 5 | public final class Location implements ILocation 6 | { 7 | public String fileName; 8 | public int line, col; 9 | 10 | public final void init ( int line, int col ) 11 | { 12 | this.line = line; 13 | this.col = col; 14 | } 15 | 16 | @Override 17 | public String getFileName () 18 | { 19 | return fileName; 20 | } 21 | 22 | @Override 23 | public final int getLine () 24 | { 25 | return line; 26 | } 27 | 28 | @Override 29 | public final int getCol () 30 | { 31 | return col; 32 | } 33 | 34 | @Override 35 | public boolean equals ( final Object o ) 36 | { 37 | if (this == o) 38 | { 39 | return true; 40 | } 41 | if (!(o instanceof Location)) 42 | { 43 | return false; 44 | } 45 | 46 | Location location = (Location)o; 47 | 48 | return col == location.col && line == location.line && 49 | !(fileName != null ? !fileName.equals( location.fileName ) : location.fileName != null); 50 | } 51 | 52 | @Override 53 | public int hashCode () 54 | { 55 | int result = fileName != null ? fileName.hashCode() : 0; 56 | result = 31 * result + line; 57 | result = 31 * result + col; 58 | return result; 59 | } 60 | 61 | @Override 62 | public String toString () 63 | { 64 | return "Location{" + 65 | "fileName='" + fileName + '\'' + 66 | ", line=" + line + 67 | ", col=" + col + 68 | '}'; 69 | } 70 | } // class 71 | -------------------------------------------------------------------------------- /java/cpp/src/c99/PlatformBits.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public class PlatformBits 4 | { 5 | public static final int CHAR_BITS = 8; 6 | public static final int SHORT_BITS = 16; 7 | public static final int INT_BITS = 16; 8 | public static final int LONG_BITS = 32; 9 | public static final int LONGLONG_BITS = 64; 10 | } // class 11 | -------------------------------------------------------------------------------- /java/cpp/src/c99/SourceRange.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public class SourceRange implements ISourceRange 4 | { 5 | public String fileName; 6 | public String fileName2; 7 | public int line1, col1; 8 | public int line2; 9 | public int col2; 10 | 11 | public SourceRange () 12 | {} 13 | 14 | public SourceRange ( ISourceRange rng ) 15 | { 16 | if (rng != null) 17 | setRange( rng ); 18 | } 19 | 20 | public final SourceRange setRange ( String fileName, int line1, int col1, String fileName2, int line2, int col2 ) 21 | { 22 | this.fileName = fileName; 23 | this.line1 = line1; 24 | this.col1 = col1; 25 | this.fileName2 = fileName2; 26 | this.line2 = line2; 27 | this.col2 = col2; 28 | return this; 29 | } 30 | 31 | public final SourceRange setRange ( String fileName, int line1, int col1, int line2, int col2 ) 32 | { 33 | this.fileName = fileName; 34 | this.line1 = line1; 35 | this.col1 = col1; 36 | this.fileName2 = null; 37 | this.line2 = line2; 38 | this.col2 = col2; 39 | return this; 40 | } 41 | 42 | public final SourceRange setRange ( ISourceRange rng ) 43 | { 44 | this.fileName = rng.getFileName(); 45 | this.line1 = rng.getLine1(); 46 | this.col1 = rng.getCol1(); 47 | this.fileName2 = rng.getFileName2(); 48 | this.line2 = rng.getLine2(); 49 | this.col2 = rng.getCol2(); 50 | return this; 51 | } 52 | 53 | public final SourceRange setRange ( int line1, int col1, int line2, int col2 ) 54 | { 55 | this.line1 = line1; 56 | this.col1 = col1; 57 | this.line2 = line2; 58 | this.col2 = col2; 59 | return this; 60 | } 61 | 62 | public final SourceRange setFileName ( String fileName ) 63 | { 64 | this.fileName = fileName; 65 | return this; 66 | } 67 | 68 | public final SourceRange setFileName2 ( String fileName2 ) 69 | { 70 | this.fileName2 = fileName2; 71 | return this; 72 | } 73 | 74 | public final SourceRange setLocation ( String fileName, int line, int col ) 75 | { 76 | return setRange( fileName, line, col, line, col ); 77 | } 78 | 79 | public final SourceRange setLocation ( int line, int col ) 80 | { 81 | return setRange( line, col, line, col ); 82 | } 83 | 84 | public final SourceRange setLocation ( ISourceRange rng ) 85 | { 86 | return setLocation( rng.getFileName(), rng.getLine1(), rng.getCol1() ); 87 | } 88 | 89 | public final SourceRange shiftExtend ( int length ) 90 | { 91 | this.line1 = this.line2; 92 | this.col1 = this.col2; 93 | this.col2 += length; 94 | return this; 95 | } 96 | 97 | public final SourceRange extendBefore ( ISourceRange end ) 98 | { 99 | this.line2 = end.getLine1(); 100 | this.col2 = end.getCol1(); 101 | return this; 102 | } 103 | 104 | public final SourceRange extend ( ISourceRange end ) 105 | { 106 | this.line2 = end.getLine2(); 107 | this.col2 = end.getCol2(); 108 | return this; 109 | } 110 | 111 | public final void translate ( int colOfs ) 112 | { 113 | this.col1 += colOfs; 114 | this.col2 += colOfs; 115 | } 116 | 117 | @Override 118 | public final String getFileName () 119 | { 120 | return fileName; 121 | } 122 | 123 | @Override 124 | public final int getLine1 () 125 | { 126 | return line1; 127 | } 128 | 129 | @Override 130 | public final int getCol1 () 131 | { 132 | return col1; 133 | } 134 | 135 | @Override 136 | public String getFileName2 () 137 | { 138 | return this.fileName2; 139 | } 140 | 141 | /** Inclusive */ 142 | @Override 143 | public final int getLine2 () 144 | { 145 | return line2; 146 | } 147 | 148 | /** Exclusive */ 149 | @Override 150 | public final int getCol2 () 151 | { 152 | return col2; 153 | } 154 | 155 | public static boolean isRealRange ( ISourceRange rng ) 156 | { 157 | return rng != null && 158 | (rng.getLine2() > rng.getLine1() || 159 | rng.getLine2() == rng.getLine1() && rng.getCol2() > rng.getCol1()); 160 | } 161 | 162 | public static String formatRange ( ISourceRange rng ) 163 | { 164 | if (rng == null) 165 | return ""; 166 | 167 | if (isRealRange( rng )) 168 | { 169 | if (rng.getLine1() != rng.getLine2()) 170 | { 171 | return String.format( "%s(%d)[%d]..(%d)[%d]", 172 | Utils.defaultString( rng.getFileName() ), 173 | rng.getLine1(), rng.getCol1(), 174 | rng.getLine2(), rng.getCol2() 175 | ); 176 | } 177 | else 178 | { 179 | return String.format( "%s(%d)[%d..%d]", 180 | Utils.defaultString( rng.getFileName() ), 181 | rng.getLine1(), rng.getCol1(), rng.getCol2() 182 | ); 183 | } 184 | } 185 | else 186 | { 187 | return String.format( "%s(%d)[%d]", 188 | Utils.defaultString( rng.getFileName() ), 189 | rng.getLine1(), rng.getCol1() 190 | ); 191 | } 192 | } 193 | 194 | @Override 195 | public String toString () 196 | { 197 | return "SourceRange{" + formatRange( this ) + '}'; 198 | } 199 | } // class 200 | -------------------------------------------------------------------------------- /java/cpp/src/c99/TypeRules.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public final class TypeRules 4 | { 5 | private TypeRules () {}; 6 | 7 | public static TypeSpec integerPromotion ( TypeSpec spec ) 8 | { 9 | // 6.3.1.1 [2] 10 | assert spec.integer; 11 | if (spec.ordinal() > TypeSpec.VOID.ordinal() && spec.ordinal() < TypeSpec.SINT.ordinal()) 12 | return (spec.width - (spec.signed?1:0) <= TypeSpec.SINT.width) ? TypeSpec.SINT : TypeSpec.UINT; 13 | else 14 | return spec; 15 | } 16 | 17 | public static TypeSpec usualArithmeticConversions ( TypeSpec s0, TypeSpec s1 ) 18 | { 19 | // 6.3.1.8 20 | 21 | TypeSpec greaterRank = s0.ordinal() > s1.ordinal() ? s0 : s1; 22 | 23 | if (greaterRank.floating) 24 | return greaterRank; 25 | 26 | s0 = integerPromotion( s0 ); 27 | s1 = integerPromotion( s1 ); 28 | 29 | // If both operands have the same type, then no further conversion is needed. 30 | if (s0 == s1) 31 | return s0; 32 | 33 | TypeSpec lesserRank; 34 | if (s0.ordinal() > s1.ordinal()) 35 | { 36 | greaterRank = s0; 37 | lesserRank = s1; 38 | } 39 | else 40 | { 41 | greaterRank = s1; 42 | lesserRank = s0; 43 | } 44 | 45 | // Otherwise, if both operands have signed integer types or both have unsigned 46 | // integer types, the operand with the type of lesser integer conversion rank is 47 | // converted to the type of the operand with greater rank. 48 | // 49 | // Otherwise, if the operand that has unsigned integer type has rank greater or 50 | // equal to the rank of the type of the other operand, then the operand with 51 | // signed integer type is converted to the type of the operand with unsigned 52 | // integer type. 53 | // 54 | // Otherwise, if the type of the operand with signed integer type can represent 55 | // all of the values of the type of the operand with unsigned integer type, then 56 | // the operand with unsigned integer type is converted to the type of the 57 | // operand with signed integer type. 58 | if (s0.signed == s1.signed || 59 | !greaterRank.signed || 60 | greaterRank.width-1 >= lesserRank.width) 61 | { 62 | return greaterRank; 63 | } 64 | 65 | // Otherwise, both operands are converted to the unsigned integer type 66 | // corresponding to the type of the operand with signed integer type. 67 | assert greaterRank.signed; 68 | assert !lesserRank.signed; 69 | 70 | return greaterRank.toUnsigned(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /java/cpp/src/c99/TypeSpec.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public enum TypeSpec 4 | { 5 | VOID("void"), 6 | 7 | BOOL("bool",false,1), 8 | // Note: the ordering matters. First , then , from smaller to larger 9 | SCHAR("signed char",true, PlatformBits.CHAR_BITS), 10 | UCHAR("unsigned char",false, PlatformBits.CHAR_BITS), 11 | SSHORT("short",true, PlatformBits.SHORT_BITS), 12 | USHORT("unsigned short",false, PlatformBits.SHORT_BITS), 13 | SINT("int",true, PlatformBits.INT_BITS), 14 | UINT("unsigned",false, PlatformBits.INT_BITS), 15 | SLONG("long",true, PlatformBits.LONG_BITS), 16 | ULONG("unsigned long",false, PlatformBits.LONG_BITS), 17 | SLLONG("long long",true, PlatformBits.LONGLONG_BITS), 18 | ULLONG("unsigned long long",false, PlatformBits.LONGLONG_BITS), 19 | FLOAT("float",32, Float.MIN_VALUE, Float.MAX_VALUE), 20 | DOUBLE("double",64, Double.MIN_VALUE, Double.MAX_VALUE), 21 | LDOUBLE("long double",64, Double.MIN_VALUE, Double.MAX_VALUE), 22 | 23 | ATOMIC("_Atomic"), 24 | COMPLEX("_Complex"), 25 | IMAGINARY("_Imaginary"), 26 | 27 | ENUM("enum"), 28 | 29 | ARRAY("[]"), 30 | STRUCT("struct"), 31 | UNION("union"), 32 | FUNCTION("()"), 33 | POINTER("*"), 34 | 35 | ERROR("error"); 36 | 37 | public static final TypeSpec INT_FIRST = BOOL; 38 | public static final TypeSpec INT_LAST = ULLONG; 39 | public static final TypeSpec INTMAX_T = SLLONG; 40 | public static final TypeSpec UINTMAX_T = ULLONG; 41 | public static final TypeSpec PTRDIFF_T = SINT; 42 | public static final TypeSpec SIZE_T = UINT; 43 | public static final TypeSpec UINTPTR_T = ULONG; 44 | 45 | public final String str; 46 | 47 | public final boolean arithmetic; 48 | public final boolean floating; 49 | public final boolean integer; 50 | public final boolean signed; 51 | public final int width; 52 | public final int sizeOf; //< sizeof() 53 | public final long longMask; 54 | public final long minValue; 55 | public final long maxValue; 56 | public final double minReal; 57 | public final double maxReal; 58 | 59 | TypeSpec ( String str ) 60 | { 61 | this.str = str; 62 | this.arithmetic = false; 63 | this.floating = false; 64 | this.integer = false; 65 | this.signed = false; 66 | this.width = 0; 67 | this.sizeOf = 0; 68 | this.longMask = 0; 69 | this.minValue = 0; 70 | this.maxValue = 0; 71 | this.minReal = 0; 72 | this.maxReal = 0; 73 | } 74 | 75 | TypeSpec ( String str, int width, double minReal, double maxReal ) 76 | { 77 | assert width > 0; 78 | this.str = str; 79 | this.arithmetic = true; 80 | this.floating = true; 81 | this.integer = false; 82 | this.signed = true; 83 | this.width = width; 84 | this.sizeOf = width / PlatformBits.CHAR_BITS; assert width % PlatformBits.CHAR_BITS == 0; 85 | this.longMask = this.width < 64 ? (1L << this.width) - 1 : ~0L; 86 | this.minValue = 0; 87 | this.maxValue = 0; 88 | this.minReal = minReal; 89 | this.maxReal = maxReal; 90 | } 91 | 92 | TypeSpec ( String str, boolean signed, int width ) 93 | { 94 | assert width > 0; 95 | this.str = str; 96 | this.arithmetic = true; 97 | this.floating = false; 98 | this.integer = true; 99 | this.signed = signed; 100 | this.width = width; 101 | this.sizeOf = (width==1?8:width) / PlatformBits.CHAR_BITS; assert (width==1?8:width) % PlatformBits.CHAR_BITS == 0; 102 | this.longMask = this.width < 64 ? (1L << this.width) - 1 : ~0L; 103 | 104 | if (signed) 105 | { 106 | this.maxValue = this.longMask >>> 1; 107 | this.minValue = -this.maxValue - 1; 108 | } 109 | else 110 | { 111 | this.minValue = 0; 112 | this.maxValue = this.longMask; 113 | } 114 | this.minReal = 0; 115 | this.maxReal = 0; 116 | } 117 | 118 | public final TypeSpec toSigned () 119 | { 120 | assert this.integer && this != BOOL; 121 | return this.signed ? this : values()[this.ordinal() - 1]; 122 | } 123 | public final TypeSpec toUnsigned () 124 | { 125 | assert this.integer; 126 | return this.signed ? values()[this.ordinal() + 1] : this; 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /java/cpp/src/c99/Utils.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | public final class Utils 4 | { 5 | private Utils () {} 6 | 7 | public static boolean equals ( Object a, Object b ) 8 | { 9 | return a == b || !(a == null || b == null) && a.equals( b ); 10 | } 11 | 12 | public static boolean isEmpty ( String x ) 13 | { 14 | return x == null || x.isEmpty(); 15 | } 16 | 17 | public static boolean isNotEmpty ( String x ) 18 | { 19 | return x == null || !x.isEmpty(); 20 | } 21 | 22 | public static String defaultIfEmpty ( String x, String def ) 23 | { 24 | return isNotEmpty( x ) ? x : def; 25 | } 26 | 27 | public static String defaultString ( String x ) 28 | { 29 | return defaultIfEmpty( x, "" ); 30 | } 31 | 32 | public static String asciiString ( byte[] bytes, int from, int count ) 33 | { 34 | char value[] = new char[count]; 35 | 36 | for ( int i = 0; i < count; ++i ) 37 | value[i] = (char)(bytes[i + from] & 0xff); 38 | 39 | return new String( value ); 40 | } 41 | 42 | public static String asciiString ( byte[] bytes ) 43 | { 44 | return asciiString( bytes, 0, bytes.length ); 45 | } 46 | 47 | public static byte[] asciiBytes ( String x ) 48 | { 49 | byte[] res = new byte[x.length()]; 50 | for ( int len = x.length(), i = 0; i < len; ++i ) 51 | res[i] = (byte)x.charAt( i ); 52 | return res; 53 | } 54 | 55 | public static boolean equals ( byte[] a, int offA, byte[] b, int offB, int len ) 56 | { 57 | assert offA + len <= a.length && offB + len <= b.length; 58 | final int end = offA + len; 59 | for ( ; offA < end; ++offA, ++offB ) 60 | if (a[offA] != b[offB]) 61 | return false; 62 | 63 | return true; 64 | } 65 | 66 | public static int compare ( byte[] a, int offA, int lenA, byte[] b, int offB, int lenB ) 67 | { 68 | int len = Math.min(lenA, lenB); 69 | int end = offA + len; 70 | for ( ; offA < end; ++offA, ++offB ) 71 | { 72 | int d = (a[offA] & 255) - (b[offB] & 255); 73 | if (d != 0) 74 | return d; 75 | } 76 | return len < lenB ? -1 : (len < lenA ? +1 : 0); 77 | } 78 | } // class 79 | -------------------------------------------------------------------------------- /java/cpp/src/c99/driver/PPSymTable.java: -------------------------------------------------------------------------------- 1 | package c99.driver; 2 | 3 | import c99.parser.IdentTable; 4 | import c99.parser.pp.PPSymbol; 5 | 6 | public class PPSymTable extends IdentTable 7 | { 8 | @Override 9 | protected PPSymbol newIdent ( byte[] bytes, int hash ) 10 | { 11 | return new PPSymbol( bytes, hash ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /java/cpp/src/c99/driver/Preprocessor.java: -------------------------------------------------------------------------------- 1 | package c99.driver; 2 | 3 | import java.io.FileInputStream; 4 | 5 | import c99.DummyErrorReporter; 6 | import c99.parser.Code; 7 | import c99.parser.pp.*; 8 | 9 | public class Preprocessor 10 | { 11 | 12 | private static boolean needWS ( Code t1, Code t2 ) 13 | { 14 | switch (t1) 15 | { 16 | case IDENT: 17 | case INT_NUMBER: 18 | case REAL_NUMBER: 19 | return t2 == Code.IDENT || t2 == Code.INT_NUMBER || t2 == Code.REAL_NUMBER; 20 | 21 | case NEWLINE: 22 | return t2 == Code.HASH; 23 | 24 | case HASH: 25 | return t2 == Code.HASH; 26 | 27 | case PLUS: 28 | return t2 == Code.EQUALS || t2 == Code.PLUS; 29 | case MINUS: 30 | return t2 == Code.EQUALS || t2 == Code.MINUS || t2 == Code.GREATER; 31 | case ASTERISK: 32 | return t2 == Code.EQUALS || t2 == Code.SLASH; 33 | case SLASH: 34 | return t2 == Code.EQUALS || t2 == Code.SLASH || t2 == Code.ASTERISK; 35 | case PERCENT: 36 | case CARET: 37 | case BANG: 38 | case EQUALS: 39 | return t2 == Code.EQUALS; 40 | case AMPERSAND: 41 | return t2 == Code.EQUALS || t2 == Code.AMPERSAND; 42 | case VERTICAL: 43 | return t2 == Code.EQUALS || t2 == Code.VERTICAL; 44 | 45 | case GREATER: 46 | return t2 == Code.GREATER || t2 == Code.EQUALS || t2 == Code.GREATER_EQUALS; 47 | case LESS: 48 | return t2 == Code.LESS || t2 == Code.EQUALS || t2 == Code.LESS_EQUALS; 49 | case GREATER_GREATER: 50 | return t2 == Code.EQUALS; 51 | case LESS_LESS: 52 | return t2 == Code.EQUALS; 53 | } 54 | return false; 55 | } 56 | 57 | public static void main ( String[] args ) 58 | { 59 | try 60 | { 61 | boolean cpp = true; 62 | boolean toks = false; 63 | String fileName = null; 64 | 65 | PreprOptions opts = new PreprOptions(); 66 | SearchPathFactory incSearch = new SearchPathFactory(); 67 | 68 | for ( int i = 0; i < args.length; ++i ) 69 | { 70 | final String arg = args[i]; 71 | 72 | if ("--toks".equals(arg)) 73 | { 74 | toks = true; 75 | cpp = false; 76 | } 77 | else if ("--no-toks".equals( arg )) 78 | toks = false; 79 | else if ("--cpp".equals( arg )) 80 | cpp = true; 81 | else if ("--no-cpp".equals( arg )) 82 | cpp = false; 83 | else if ("--nostdinc".equals( arg )) 84 | opts.setNoStdInc( true ); 85 | else if (arg.startsWith("-I") || arg.startsWith("-i")) 86 | { 87 | String tmp = arg.substring( 2 ); 88 | if (tmp.length() == 0) 89 | { 90 | System.err.println( "**fatal: missing argument for " + arg ); 91 | System.exit(1); 92 | } 93 | if (arg.startsWith("-I")) 94 | incSearch.addInclude( tmp ); 95 | else 96 | incSearch.addQuotedInclude(tmp); 97 | } 98 | else if (arg.startsWith( "-")) 99 | { 100 | System.err.println( "**fatal: unknown command line option '"+arg +"'" ); 101 | System.exit(1); 102 | } 103 | else 104 | { 105 | if (fileName != null) 106 | { 107 | System.err.println( "**fatal: More than one input filename specified" ); 108 | System.exit(1); 109 | } 110 | fileName = arg; 111 | } 112 | } 113 | 114 | if (fileName == null) 115 | { 116 | System.err.println( "**fatal: No input filename specified" ); 117 | System.exit(1); 118 | } 119 | 120 | DummyErrorReporter reporter = new DummyErrorReporter(); 121 | PPSymTable symTable = new PPSymTable(); 122 | Prepr pp = new Prepr( opts, reporter, incSearch.finish( opts ), 123 | fileName, new FileInputStream( fileName ), symTable ); 124 | 125 | String lastFile = ""; 126 | int lastLine = -1; 127 | PPLexer.Token tok; 128 | Code lastTok = Code.NEWLINE; 129 | boolean nl = true; 130 | do 131 | { 132 | tok = pp.nextToken(); 133 | if (!tok.getFileName().equals( lastFile )) 134 | { 135 | if (cpp) 136 | { 137 | if (!nl) 138 | System.out.println(); 139 | System.out.format( "# %d %s\n", tok.getLine1(), Misc.simpleEscapeString( 140 | tok.getFileName() )); 141 | nl = true; 142 | lastTok = Code.NEWLINE; 143 | } 144 | lastLine = tok.getLine1(); 145 | } 146 | else if (tok.getLine1() != lastLine) 147 | { 148 | if (tok.getLine1() - lastLine <= 10) 149 | { 150 | do 151 | { 152 | if (cpp) System.out.println(); 153 | } 154 | while (++lastLine < tok.getLine1()); 155 | nl = true; 156 | lastTok = Code.NEWLINE; 157 | } 158 | else 159 | { 160 | if (cpp) 161 | { 162 | if (!nl) 163 | System.out.println(); 164 | System.out.format( "# %d %s\n", tok.getLine1(), Misc.simpleEscapeString(tok.getFileName())); 165 | nl = true; 166 | lastTok = Code.NEWLINE; 167 | } 168 | } 169 | lastLine = tok.getLine1(); 170 | } 171 | 172 | lastFile = tok.getFileName(); 173 | 174 | if (cpp) 175 | { 176 | if (tok.code() != Code.NEWLINE) 177 | { 178 | if (nl) 179 | { 180 | for ( int i = 1, col = tok.getCol1(); i < col; ++i ) 181 | { 182 | System.out.print( ' ' ); 183 | lastTok = Code.WHITESPACE; 184 | } 185 | } 186 | if (needWS( lastTok, tok.code() )) 187 | System.out.print( ' ' ); 188 | lastTok = tok.code(); 189 | tok.output( System.out ); 190 | nl = false; 191 | } 192 | } 193 | if (toks) System.out.println( tok ); 194 | } 195 | while (tok.code() != Code.EOF); 196 | } 197 | catch (Exception e) 198 | { 199 | e.printStackTrace(); 200 | } 201 | } 202 | } // class 203 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/Code.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | public enum Code 4 | { 5 | EOF, 6 | IDENT, 7 | TYPENAME, 8 | INT_NUMBER, 9 | REAL_NUMBER, 10 | CHAR_CONST, 11 | WIDE_CHAR_CONST, // u,U,L 12 | STRING_CONST, 13 | WIDE_STRING_CONST, // u8, u, U, L 14 | 15 | L_BRACKET("["), R_BRACKET("]"), 16 | L_PAREN("("), R_PAREN(")"), 17 | L_CURLY("{"), R_CURLY("}"), 18 | FULLSTOP("."), 19 | MINUS_GREATER("->"), 20 | 21 | PLUS_PLUS("++"), 22 | MINUS_MINUS("--"), 23 | AMPERSAND("&"), 24 | ASTERISK("*"), 25 | PLUS("+"), 26 | MINUS("-"), 27 | TILDE("~"), 28 | BANG("!"), 29 | 30 | SLASH("/"), 31 | PERCENT("%"), 32 | LESS_LESS("<<"), 33 | GREATER_GREATER(">>"), 34 | LESS("<"), 35 | GREATER(">"), 36 | LESS_EQUALS("<="), 37 | GREATER_EQUALS(">="), 38 | EQUALS_EQUALS("=="), 39 | BANG_EQUALS("!="), 40 | CARET("^"), 41 | VERTICAL("|"), 42 | AMPERSAND_AMPERSAND("&&"), 43 | VERTICAL_VERTICAL("||"), 44 | 45 | QUESTION("?"), 46 | COLON(":"), 47 | SEMICOLON(";"), 48 | ELLIPSIS("..."), 49 | 50 | EQUALS("="), 51 | ASTERISK_EQUALS("*="), 52 | SLASH_EQUALS("/="), 53 | PERCENT_EQUALS("%="), 54 | PLUS_EQUALS("+="), 55 | MINUS_EQUALS("-="), 56 | LESS_LESS_EQUALS("<<="), 57 | GREATER_GREATER_EQUALS(">>="), 58 | AMPERSAND_EQUALS("&="), 59 | CARET_EQUALS("^="), 60 | VERTICAL_EQUALS("|="), 61 | 62 | COMMA(","), 63 | 64 | // Parser-only 65 | AUTO("auto"), 66 | BREAK("break"), 67 | CASE("case"), 68 | CHAR("char"), 69 | CONST("const"), 70 | CONTINUE("continue"), 71 | DEFAULT("default"), 72 | DO("do"), 73 | DOUBLE("double"), 74 | ELSE("else"), 75 | ENUM("enum"), 76 | EXTERN("extern"), 77 | FLOAT("float"), 78 | FOR("for"), 79 | GOTO("goto"), 80 | IF("if"), 81 | INLINE("inline"), 82 | INT("int"), 83 | LONG("long"), 84 | REGISTER("register"), 85 | RESTRICT("restrict"), 86 | RETURN("return"), 87 | SHORT("short"), 88 | SIGNED("signed"), 89 | SIZEOF("sizeof"), 90 | STATIC("static"), 91 | STRUCT("struct"), 92 | SWITCH("switch"), 93 | TYPEDEF("typedef"), 94 | UNION("union"), 95 | UNSIGNED("unsigned"), 96 | VOID("void"), 97 | VOLATILE("volatile"), 98 | WHILE("while"), 99 | _ALIGNAS("_Alignas"), 100 | _ALIGNOF("_Alignof"), 101 | _ATOMIC("_Atomic"), 102 | _BOOL("_Bool"), 103 | _COMPLEX("_Complex"), 104 | _GENERIC("_Generic"), 105 | _IMAGINARY("_Imaginary"), 106 | _NORETURN("_Noreturn"), 107 | _STATIC_ASSERT("_Static_assert"), 108 | _THREAD_LOCAL("_Thread_local"), 109 | GCC_ASM("__asm__"), 110 | GCC_VOLATILE("__volatile__"), 111 | GCC_TYPEOF("__typeof__"), 112 | GCC_LABEL("__label__"), 113 | GCC_ALIGNOF("__alignof__"), 114 | GCC_ATTRIBUTE("__attribute__"), 115 | 116 | // Preprocessor-only 117 | HASH("#"), 118 | HASH_HASH("##"), 119 | 120 | OTHER, 121 | 122 | WHITESPACE(" "), 123 | NEWLINE, 124 | ANGLED_INCLUDE, 125 | 126 | /** Macro parameter reference*/ 127 | MACRO_PARAM, 128 | /** '##' token */ 129 | CONCAT; 130 | 131 | public final byte[] printable; 132 | public final String str; 133 | 134 | public static final Code FIRST_KW = AUTO; 135 | public static final Code LAST_KW = GCC_ATTRIBUTE; 136 | 137 | Code () 138 | { 139 | str = ""; 140 | printable = new byte[0]; 141 | } 142 | 143 | Code ( String str ) 144 | { 145 | this.str = str; 146 | this.printable = str.getBytes(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/IdentTable.java: -------------------------------------------------------------------------------- 1 | package c99.parser; 2 | 3 | import c99.Ident; 4 | import c99.Utils; 5 | 6 | import java.nio.charset.Charset; 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | 10 | public abstract class IdentTable 11 | { 12 | private static final class Key 13 | { 14 | int hash; 15 | byte val[]; 16 | int offset; 17 | int count; 18 | 19 | Key () {} 20 | 21 | Key ( final int hash, final byte[] val, int offset, int count ) 22 | { 23 | this.hash = hash; 24 | this.val = Arrays.copyOfRange( val, offset, offset + count ); 25 | this.offset = 0; 26 | this.count = count; 27 | } 28 | 29 | final void setVal ( final int hash, final byte[] val, final int offset, final int count ) 30 | { 31 | this.hash = hash; 32 | this.val = val; 33 | this.offset = offset; 34 | this.count = count; 35 | } 36 | 37 | @Override 38 | public final int hashCode () 39 | { 40 | return this.hash; 41 | } 42 | 43 | @Override 44 | public boolean equals ( final Object o ) 45 | { 46 | if (this == o) 47 | return true; 48 | if (!(o instanceof Key)) 49 | return false; 50 | 51 | Key key = (Key)o; 52 | 53 | return 54 | hash == key.hash && 55 | count == key.count && 56 | Utils.equals( this.val, this.offset, key.val, key.offset, this.count ); 57 | } 58 | 59 | @Override 60 | public String toString () 61 | { 62 | return "Key{" + 63 | "hash=" + hash + 64 | ", count=" + count + 65 | '}'; 66 | } 67 | } 68 | 69 | private final HashMap m_map = new HashMap(); 70 | private final Key m_dummyKey = new Key(); 71 | 72 | public final T symbol ( byte val[], int offset, int len ) 73 | { 74 | m_dummyKey.setVal( Ident.calcHashCode( val, offset, len ), val, offset, len ); 75 | 76 | T symbol = m_map.get( m_dummyKey ); 77 | if (symbol == null) 78 | { 79 | Key key = new Key( m_dummyKey.hash, val, offset, len ); 80 | symbol = newIdent( key.val, m_map.size() + 1 ); 81 | m_map.put( key, symbol ); 82 | } 83 | 84 | return symbol; 85 | } 86 | 87 | private static final Charset s_latin = Charset.forName( "ISO-8859-1" ); 88 | 89 | public final T symbol ( String name ) 90 | { 91 | byte[] bytes = name.getBytes( s_latin ); 92 | return symbol( bytes, 0, bytes.length ); 93 | } 94 | 95 | protected abstract T newIdent ( byte[] bytes, int hash ); 96 | 97 | } // class 98 | 99 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/Builtin.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | /** 4 | * Created by ceco on 7/20/14. 5 | */ 6 | enum Builtin 7 | { 8 | __LINE__, 9 | __FILE__, 10 | __DATE__ 11 | } 12 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/ConcatToken.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | 6 | import c99.parser.Code; 7 | 8 | /** 9 | * A '##' between two tokens. 10 | * 11 | * It is left associative, meaning that multiple '##'-s aways generate a left tree. 12 | * 'a ## b ## c' always produces 13 | *

{@code concat( concat( a, b ), c )} 14 | */ 15 | final class ConcatToken extends PPDefs.AbstractToken 16 | { 17 | final PPDefs.AbstractToken tokens[]; 18 | 19 | public ConcatToken ( PPDefs.AbstractToken left, PPDefs.AbstractToken right ) 20 | { 21 | assert !(right instanceof ConcatToken); 22 | 23 | m_code = Code.CONCAT; 24 | if (!(left instanceof ConcatToken)) 25 | this.tokens = new PPDefs.AbstractToken[]{ left, right }; 26 | else 27 | { 28 | final ConcatToken lt = (ConcatToken)left; 29 | final int len = lt.tokens.length; 30 | this.tokens = new PPDefs.AbstractToken[len+1]; 31 | System.arraycopy( lt.tokens, 0, this.tokens, 0, len ); 32 | this.tokens[len] = right; 33 | } 34 | } 35 | 36 | ConcatToken ( PPDefs.AbstractToken[] tokens ) 37 | { 38 | this.tokens = tokens; 39 | } 40 | 41 | @SuppressWarnings("CloneDoesntCallSuperClone") 42 | @Override 43 | public ConcatToken clone () 44 | { 45 | PPDefs.AbstractToken[] t = new PPDefs.AbstractToken[this.tokens.length]; 46 | for ( int i = 0; i < this.tokens.length; ++i ) 47 | t[i] = this.tokens[i].clone(); 48 | ConcatToken res = new ConcatToken( t ); 49 | res.setRange( this ); 50 | return res; 51 | } 52 | 53 | @Override 54 | public boolean same ( final PPDefs.AbstractToken tok ) 55 | { 56 | if (tok.m_code != m_code) 57 | return false; 58 | ConcatToken t = (ConcatToken)tok; 59 | if (this.tokens.length != t.tokens.length) 60 | return false; 61 | for ( int i = 0; i < tokens.length; ++i ) 62 | if (!this.tokens[i].same( t.tokens[i] )) 63 | return false; 64 | return true; 65 | } 66 | 67 | @Override 68 | public int length () 69 | { 70 | int len = 0; 71 | for ( PPDefs.AbstractToken tok : this.tokens ) 72 | len += tok.length(); 73 | return len; 74 | } 75 | 76 | @Override 77 | public String toString () 78 | { 79 | StringBuilder b = new StringBuilder(); 80 | b.append( "ConcatToken{" ); 81 | for ( int i = 0; i < this.tokens.length; ++i ) 82 | { 83 | if (i > 0) 84 | b.append( ", " ); 85 | b.append( i ).append( '=' ).append( this.tokens[i].toString() ); 86 | } 87 | b.append( '}' ); 88 | return b.toString(); 89 | } 90 | 91 | private static final byte[] s_text = " ## ".getBytes(); 92 | @Override 93 | public void output ( final OutputStream out ) throws IOException 94 | { 95 | for ( int i = 0; i < this.tokens.length; ++i ) 96 | { 97 | if (i > 0) 98 | out.write( s_text ); 99 | this.tokens[i].output( out ); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/IIncludeLocator.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import java.io.InputStream; 4 | 5 | public interface IIncludeLocator 6 | { 7 | /** 8 | * 9 | * @param fileName file name to open 10 | * @return null on error 11 | */ 12 | public InputStream locate ( String fileName ); 13 | } 14 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/IPreprOptions.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | public interface IPreprOptions 4 | { 5 | boolean getNoStdInc (); 6 | boolean getGccExtensions (); 7 | boolean getWarnUndef (); 8 | 9 | int getMaxIncludeDepth (); 10 | } 11 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/ISearchPath.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | public interface ISearchPath 4 | { 5 | class Result 6 | { 7 | public final String path; 8 | public final String absPath; 9 | 10 | public Result ( final String path, final String absPath ) 11 | { 12 | this.path = path; 13 | this.absPath = absPath; 14 | } 15 | 16 | @Override 17 | public String toString () 18 | { 19 | return "Result{" + 20 | "path='" + path + '\'' + 21 | ", absPath='" + absPath + '\'' + 22 | '}'; 23 | } 24 | } 25 | 26 | public Result searchQuoted ( String curFile, String fileName ); 27 | public Result searchAngled ( String fileName ); 28 | } 29 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/LineReader.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.Arrays; 6 | 7 | import c99.FatalException; 8 | import c99.Location; 9 | import c99.SourceRange; 10 | 11 | public final class LineReader 12 | { 13 | private final InputStream m_input; 14 | private byte m_buf[]; 15 | private int m_lineStart, m_limit; 16 | private boolean m_inputEOF; 17 | private boolean m_linesEOF; 18 | 19 | private int m_lineEnd; 20 | private int m_consumePos; 21 | private int m_startLineNumber; 22 | private int m_curLineNumber; 23 | 24 | /** A map of the line breaks in a concatenated line */ 25 | private int m_lineMap[] = new int[32]; 26 | private int m_lineMapCount; 27 | 28 | public LineReader ( InputStream input, int bufSize ) 29 | { 30 | m_input = input; 31 | m_buf = new byte[bufSize]; 32 | m_lineStart = 0; 33 | m_limit = 0; 34 | m_inputEOF = false; 35 | m_linesEOF = false; 36 | 37 | m_lineEnd = 0; 38 | m_consumePos = 0; 39 | m_startLineNumber = m_curLineNumber = 0; 40 | 41 | m_lineMapCount = 0; 42 | } 43 | 44 | public final void close () 45 | { 46 | try 47 | { 48 | m_input.close(); 49 | } 50 | catch (IOException e) 51 | { 52 | } 53 | } 54 | 55 | private void resetMap () 56 | { 57 | m_lineMapCount = 0; 58 | } 59 | 60 | private void addMapEntry ( int ofs ) 61 | { 62 | if (m_lineMapCount == m_lineMap.length) // Resize if necessary 63 | m_lineMap = Arrays.copyOf( m_lineMap, m_lineMap.length * 2 ); 64 | 65 | m_lineMap[m_lineMapCount++] = ofs; 66 | } 67 | 68 | /** 69 | * 70 | * @return false if no new data was filled 71 | */ 72 | private boolean fill () 73 | { 74 | if (m_inputEOF) 75 | return false; 76 | 77 | if (m_limit == m_buf.length) 78 | { 79 | if (m_lineStart == m_limit) 80 | { 81 | m_limit = 0; 82 | m_lineStart = 0; 83 | } 84 | else if (m_lineStart > 0) 85 | { 86 | int len = m_limit - m_lineStart; 87 | System.arraycopy( m_buf, m_lineStart, m_buf, 0, len ); 88 | m_lineStart = 0; 89 | m_limit = len; 90 | } 91 | else 92 | { 93 | // Buffer is completely full. Resize the buffer. 94 | m_buf = Arrays.copyOf( m_buf, m_buf.length * 2 ); 95 | } 96 | } 97 | 98 | try 99 | { 100 | int n; 101 | n = m_input.read( m_buf, m_limit, m_buf.length - m_limit ); 102 | if (n >= 0) 103 | m_limit += n; 104 | 105 | if (m_limit < m_buf.length) 106 | { 107 | m_buf[m_limit] = 0; // Add a sentinel to avoid range checks at EOF 108 | m_inputEOF = true; 109 | } 110 | 111 | return n > 0; 112 | } 113 | catch (IOException e) 114 | { 115 | throw new FatalException( e ); 116 | } 117 | } 118 | 119 | public boolean readNextLine () 120 | { 121 | if (m_linesEOF) 122 | return false; 123 | 124 | m_lineStart = m_consumePos; // consume the previous line 125 | m_startLineNumber = ++m_curLineNumber; 126 | resetMap(); 127 | 128 | int ofs = 0; // offset from mark 129 | for(;;) 130 | { 131 | int i; 132 | for ( i = m_lineStart + ofs; i < m_limit && m_buf[i] != '\n'; ++i ) 133 | {} 134 | 135 | if (i < m_limit) 136 | { 137 | m_lineEnd = i + 1; 138 | break; 139 | } 140 | 141 | ofs = i - m_lineStart; 142 | if (!fill()) 143 | { 144 | m_lineEnd = m_limit; 145 | m_linesEOF = true; 146 | break; 147 | } 148 | } 149 | m_consumePos = m_lineEnd; 150 | return true; 151 | } 152 | 153 | public boolean appendNextLine ( int at ) 154 | { 155 | assert at >= m_lineStart && at < m_lineEnd; 156 | 157 | if (m_linesEOF) 158 | return false; 159 | 160 | ++m_curLineNumber; 161 | at -= m_lineStart; // Convert to offset 162 | addMapEntry( at ); 163 | 164 | int newStartOfs = m_consumePos - m_lineStart; // convert to offset 165 | int ofs = newStartOfs; 166 | for(;;) 167 | { 168 | int i; 169 | for ( i = m_lineStart + ofs; i < m_limit && m_buf[i] != '\n'; ++i ) 170 | {} 171 | 172 | if (i < m_limit) 173 | { 174 | m_lineEnd = i + 1; 175 | break; 176 | } 177 | 178 | ofs = i - m_lineStart; 179 | if (!fill()) 180 | { 181 | m_lineEnd = m_limit; 182 | m_linesEOF = true; 183 | break; 184 | } 185 | } 186 | 187 | m_consumePos = m_lineEnd; 188 | 189 | // The new line is between [m_lineStart+newStartOfs..m_lineEnd). Append it. 190 | int newStart = m_lineStart + newStartOfs; // Convert to abs 191 | int newLen = m_lineEnd - newStart; 192 | at += m_lineStart; // convert back to abs 193 | 194 | if (newLen > 0) 195 | System.arraycopy( m_buf, newStart, m_buf, at, newLen ); 196 | m_lineEnd = at + newLen; 197 | 198 | return true; 199 | } 200 | 201 | public byte[] getLineBuf () 202 | { 203 | return m_buf; 204 | } 205 | 206 | public int getLineStart () 207 | { 208 | return m_lineStart; 209 | } 210 | 211 | public int getLineEnd () 212 | { 213 | return m_lineEnd; 214 | } 215 | 216 | public int getCurLineNumber () 217 | { 218 | return m_curLineNumber; 219 | } 220 | 221 | private final Location m_tmpLoc = new Location(); 222 | 223 | public final void calcRangeStart ( int from, SourceRange rng ) 224 | { 225 | calcLocation( from, m_tmpLoc ); 226 | rng.line1 = m_tmpLoc.line; 227 | rng.col1 = m_tmpLoc.col; 228 | } 229 | 230 | public final SourceRange calcRangeEnd ( int to, SourceRange rng ) 231 | { 232 | calcLocation( to - 1, m_tmpLoc ); 233 | rng.line2 = m_tmpLoc.line; 234 | rng.col2 = m_tmpLoc.col+1; 235 | return rng; 236 | } 237 | 238 | public final SourceRange calcRange ( int from, int to, SourceRange rng ) 239 | { 240 | calcRangeStart( from, rng ); 241 | 242 | if (to > from) 243 | calcRangeEnd( to, rng ); 244 | else 245 | { 246 | rng.line2 = rng.line1; 247 | rng.col2 = rng.col1; 248 | } 249 | return rng; 250 | } 251 | 252 | private void calcLocation ( int pos, Location loc ) 253 | { 254 | pos -= m_lineStart; // Convert into offset 255 | 256 | int line = m_startLineNumber; 257 | for ( int i = m_lineMapCount - 1; i >= 0; --i ) 258 | { 259 | if (pos >= m_lineMap[i]) 260 | { 261 | pos -= m_lineMap[i]; 262 | line += i + 1; 263 | break; 264 | } 265 | } 266 | 267 | loc.init( line, pos + 1 ); 268 | } 269 | 270 | } // class 271 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/Macro.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import c99.ISourceRange; 4 | import c99.SourceRange; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Iterator; 8 | 9 | final class Macro 10 | { 11 | public final SourceRange nameLoc = new SourceRange(); 12 | public final SourceRange bodyLoc = new SourceRange(); 13 | public final PPSymbol symbol; 14 | public final Builtin builtin; 15 | public boolean funcLike; 16 | public boolean variadic; 17 | public boolean expanding; 18 | 19 | public final ArrayList params = new ArrayList(); 20 | public final TokenList body = new TokenList(); 21 | 22 | Macro ( final PPSymbol symbol, ISourceRange nameLoc, Builtin builtin ) 23 | { 24 | this.symbol = symbol; 25 | this.nameLoc.setRange( nameLoc ); 26 | this.builtin = builtin; 27 | } 28 | 29 | final int paramCount () 30 | { 31 | return params.size(); 32 | } 33 | 34 | void cleanUpParamScope () 35 | { 36 | for ( ParamDecl param : params ) 37 | param.cleanUp(); 38 | } 39 | 40 | boolean same ( Macro m ) 41 | { 42 | if (this.symbol != m.symbol || 43 | this.funcLike != m.funcLike || 44 | this.params.size() != m.params.size() || 45 | this.body.size() != m.body.size()) 46 | { 47 | return false; 48 | } 49 | 50 | Iterator p1 = this.params.iterator(); 51 | Iterator p2 = m.params.iterator(); 52 | while (p1.hasNext()) 53 | if (!p1.next().same( p2.next() )) 54 | return false; 55 | 56 | Iterator t1 = this.body.iterator(); 57 | Iterator t2 = m.body.iterator(); 58 | while (t1.hasNext()) 59 | if (!t1.next().same( t2.next() )) 60 | return false; 61 | 62 | return true; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/Misc.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | public final class Misc 4 | { 5 | private Misc () {} 6 | 7 | public static String simpleEscapeString ( String str ) 8 | { 9 | final StringBuilder buf = new StringBuilder( str.length() + 8 ); 10 | buf.append( '"' ); 11 | for ( int len = str.length(), i = 0; i < len; ++i ) 12 | { 13 | final char ch = str.charAt( i ); 14 | if (ch == '"' || ch == '\\') 15 | buf.append( '\\' ); 16 | else if (ch < 32) 17 | { 18 | buf.append( '\\' ) 19 | .append( (ch >>> 6) & 7 ) 20 | .append( (ch >>> 3) & 7 ) 21 | .append( ch & 7 ); 22 | } 23 | buf.append( ch ); 24 | } 25 | buf.append( '"' ); 26 | return buf.toString(); 27 | } 28 | 29 | 30 | } // class 31 | 32 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/PPDefs.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import c99.*; 4 | import c99.parser.Code; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | import java.util.Arrays; 10 | 11 | public interface PPDefs 12 | { 13 | 14 | public abstract static class AbstractToken extends SourceRange implements Cloneable 15 | { 16 | protected Code m_code; 17 | 18 | AbstractToken m_next, m_prev; 19 | 20 | @SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException") 21 | public abstract AbstractToken clone (); 22 | 23 | public abstract boolean same ( AbstractToken tok ); 24 | 25 | public abstract int length (); 26 | 27 | public final Code code () 28 | { 29 | return m_code; 30 | } 31 | 32 | @Override 33 | public String toString () 34 | { 35 | return "Token{" + 36 | "code=" + m_code + 37 | "} " + super.toString(); 38 | } 39 | 40 | public abstract void output ( OutputStream out ) throws IOException; 41 | 42 | public final String outputString () 43 | { 44 | ByteArrayOutputStream out = new ByteArrayOutputStream( 16 ); 45 | try { 46 | output( out ); 47 | } catch (IOException e) { throw new Error( "Unexpected", e ); } 48 | return out.toString(); 49 | } 50 | } 51 | 52 | public static class Token extends AbstractToken 53 | { 54 | private static final int DEFAULT_LEN = 32; 55 | 56 | private int m_length; 57 | private int m_flags; 58 | private Object m_object; 59 | 60 | private final byte[] m_defaultBuf; 61 | private byte[] m_text; 62 | 63 | public Token () 64 | { 65 | m_defaultBuf = new byte[DEFAULT_LEN]; 66 | } 67 | 68 | public Token ( Code code ) 69 | { 70 | this(); 71 | setCode( code ); 72 | } 73 | 74 | public Token ( Token tok ) 75 | { 76 | m_defaultBuf = null; 77 | copyFrom( tok ); 78 | } 79 | 80 | public void copyFrom ( Token tok ) 81 | { 82 | m_code = tok.m_code; 83 | m_length = tok.m_length; 84 | m_flags = tok.m_flags; 85 | m_object = tok.m_object; 86 | if (tok.m_text != null) 87 | setText( tok.m_text, 0, tok.m_length ); 88 | setRange( tok ); 89 | } 90 | 91 | public final void reset () 92 | { 93 | m_code = null; 94 | m_length = 0; 95 | m_flags = 0; 96 | m_object = null; 97 | m_text = null; 98 | this.fileName = null; 99 | this.line1 = this.col1 = this.line2 = this.col2 = 0; 100 | } 101 | 102 | public final boolean isNoExpand () 103 | { 104 | return (m_flags & 1) != 0; 105 | } 106 | 107 | public final void setNoExpand ( boolean f ) 108 | { 109 | if (f) 110 | m_flags |= 1; 111 | else 112 | m_flags &= ~1; 113 | } 114 | 115 | public final SYM symbol () 116 | { 117 | return (SYM)m_object; 118 | } 119 | 120 | public final void setIdent ( SYM symbol ) 121 | { 122 | this.m_code = Code.IDENT; 123 | m_object = symbol; 124 | m_length = symbol.length(); 125 | } 126 | 127 | public final void setText ( byte[] buf, int from, int count ) 128 | { 129 | if (m_defaultBuf != null && count <= DEFAULT_LEN) 130 | System.arraycopy( buf, from, m_text = m_defaultBuf, 0, count ); 131 | else 132 | m_text = Arrays.copyOfRange( buf, from, from + count ); 133 | m_length = count; 134 | } 135 | 136 | /** 137 | * Like {@code #setText} but transfers the ownership of {@param buf} 138 | * instead of copying it. 139 | */ 140 | public final void setTextWithOnwership ( byte[] buf ) 141 | { 142 | m_text = buf; 143 | m_length = buf.length; 144 | } 145 | 146 | public final void setOther ( Code code, byte[] buf, int from, int count ) 147 | { 148 | m_code = code; 149 | setText( buf, from, count ); 150 | } 151 | 152 | public final void setStringConst ( byte[] origText, int from, int count, 153 | byte[] value ) 154 | { 155 | m_code = Code.STRING_CONST; 156 | setText( origText, from, count ); 157 | m_object = value; 158 | } 159 | 160 | public final void setStringConst ( String value ) 161 | { 162 | m_code = Code.STRING_CONST; 163 | m_text = Utils.asciiBytes( Misc.simpleEscapeString( value ) ); 164 | m_length = m_text.length; 165 | m_object = Utils.asciiBytes( value ); 166 | } 167 | 168 | public final byte[] getStringConstValue () 169 | { 170 | assert m_code == Code.STRING_CONST; 171 | return (byte[])m_object; 172 | } 173 | 174 | public final void setCharConst ( byte[] origText, int from, int count, Constant.IntC value ) 175 | { 176 | m_code = Code.CHAR_CONST; 177 | setText( origText, from, count ); 178 | m_object = value; 179 | } 180 | 181 | public final Constant.IntC getCharConstValue () 182 | { 183 | assert m_code == Code.CHAR_CONST; 184 | return (Constant.IntC)m_object; 185 | } 186 | 187 | /** {@link #setText(byte[], int, int)} must have already been called! */ 188 | public final void setIntConst ( Constant.IntC value ) 189 | { 190 | m_code = Code.INT_NUMBER; 191 | m_object = value; 192 | } 193 | 194 | public final void setIntConst ( int value ) 195 | { 196 | setTextWithOnwership( (""+value).getBytes() ); 197 | setIntConst( Constant.makeLong( TypeSpec.SINT, value ) ); 198 | } 199 | 200 | public final Constant.IntC getIntConstValue () 201 | { 202 | assert m_code == Code.INT_NUMBER; 203 | return (Constant.IntC)m_object; 204 | } 205 | 206 | public final void setRealConst ( Constant.RealC value ) 207 | { 208 | m_code = Code.REAL_NUMBER; 209 | m_object = value; 210 | } 211 | 212 | public final Constant.RealC getRealConst () 213 | { 214 | assert m_code == Code.REAL_NUMBER; 215 | return (Constant.RealC)m_object; 216 | } 217 | 218 | public final void setCode ( Code code ) 219 | { 220 | m_code = code; 221 | m_length = code.printable.length; 222 | } 223 | 224 | @SuppressWarnings("CloneDoesntCallSuperClone") 225 | @Override 226 | public Token clone () 227 | { 228 | return new Token(this); 229 | } 230 | 231 | @Override 232 | public boolean same ( final AbstractToken _tok ) 233 | { 234 | if (_tok instanceof Token) 235 | { 236 | final Token tok = (Token)_tok; 237 | if (!( 238 | m_code == tok.m_code && 239 | m_length == tok.m_length && 240 | (m_text == null || Utils.equals(m_text, 0, tok.m_text, 0, m_length)) 241 | )) 242 | return false; 243 | switch(m_code) 244 | { 245 | case IDENT: 246 | assert m_object instanceof PPSymbol; 247 | return m_object == tok.m_object; 248 | case STRING_CONST: 249 | return Arrays.equals( (byte[])m_object, (byte[])tok.m_object ); 250 | case CHAR_CONST: 251 | case INT_NUMBER: 252 | assert m_object instanceof Constant.IntC; 253 | return ((Constant.IntC)m_object).equals( (Constant.IntC)tok.m_object ); 254 | case REAL_NUMBER: 255 | assert m_object instanceof Constant.RealC; 256 | return ((Constant.RealC)m_object).equals( (Constant.RealC)tok.m_object ); 257 | default: 258 | assert m_object == null; 259 | return true; 260 | } 261 | } 262 | else 263 | return false; 264 | } 265 | 266 | @Override 267 | public int length () 268 | { 269 | return m_length; 270 | } 271 | 272 | public void output ( OutputStream out ) throws IOException 273 | { 274 | if (m_object instanceof PPSymbol) 275 | out.write( ((PPSymbol)m_object).bytes ); 276 | else if (m_text != null) 277 | out.write( m_text, 0, m_length ); 278 | else 279 | out.write( m_code.printable ); 280 | } 281 | 282 | @Override 283 | public String toString () 284 | { 285 | final StringBuilder sb = new StringBuilder( "Token{" ); 286 | sb.append( m_code ); 287 | if (isNoExpand()) 288 | sb.append( ", NO_EXPAND" ); 289 | if (m_object instanceof PPSymbol) 290 | sb.append( ", " ).append( (PPSymbol)m_object ); 291 | else if (m_text != null) 292 | sb.append( ", '" ).append( Utils.asciiString( m_text, 0, Math.min( m_length, DEFAULT_LEN ) ) ) 293 | .append( '\'' ); 294 | sb.append( ", " ).append( SourceRange.formatRange( this ) ); 295 | sb.append( '}' ); 296 | return sb.toString(); 297 | } 298 | 299 | public final byte[] text () 300 | { 301 | return m_text; 302 | } 303 | 304 | public final int textLen () 305 | { 306 | return m_length; 307 | } 308 | 309 | public final String textString () 310 | { 311 | return Utils.asciiString( m_text, 0, m_length ); 312 | } 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/PPSymCode.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | public enum PPSymCode 4 | { 5 | DEFINE("define"), 6 | INCLUDE("include"), 7 | LINE("line"), 8 | IF("if"), 9 | IFDEF("ifdef"), 10 | IFNDEF("ifndef"), 11 | ELSE("else"), 12 | ELIF("elif"), 13 | ENDIF("endif"), 14 | DEFINED("defined"), 15 | UNDEF("undef"), 16 | ERROR("error"), 17 | PRAGMA("pragma"), 18 | VA_ARGS("__VA_ARGS__"); 19 | 20 | public final String name; 21 | 22 | PPSymCode ( String name ) 23 | { 24 | this.name = name; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/PPSymbol.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import c99.Ident; 4 | 5 | public class PPSymbol extends Ident 6 | { 7 | public PPSymCode ppCode; 8 | public Object ppDecl; 9 | 10 | public PPSymbol ( byte[] bytes, int hash ) 11 | { 12 | super( bytes, hash ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/ParamDecl.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | final class ParamDecl 4 | { 5 | private final Object prevPPDecl; 6 | public final PPSymbol symbol; 7 | public final int index; 8 | public boolean variadic; 9 | 10 | ParamDecl ( final PPSymbol symbol, int index, boolean variadic ) 11 | { 12 | this.prevPPDecl = symbol.ppDecl; 13 | this.symbol = symbol; 14 | this.index = index; 15 | this.variadic = variadic; 16 | 17 | assert !(symbol.ppDecl instanceof ParamDecl); 18 | symbol.ppDecl = this; 19 | } 20 | 21 | public final boolean same ( ParamDecl p ) 22 | { 23 | return this.symbol == p.symbol && this.index == p.index; 24 | } 25 | 26 | void cleanUp () 27 | { 28 | assert symbol.ppDecl == this; 29 | symbol.ppDecl = prevPPDecl; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/ParamToken.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | 6 | import c99.parser.Code; 7 | 8 | final class ParamToken extends PPDefs.AbstractToken 9 | { 10 | public final ParamDecl param; 11 | public boolean stringify; 12 | 13 | ParamToken ( final ParamDecl param ) 14 | { 15 | m_code = Code.MACRO_PARAM; 16 | this.param = param; 17 | } 18 | 19 | @SuppressWarnings("CloneDoesntCallSuperClone") 20 | @Override 21 | public ParamToken clone () 22 | { 23 | ParamToken res = new ParamToken( this.param ); 24 | res.setRange( this ); 25 | return res; 26 | } 27 | 28 | @Override 29 | public boolean same ( final PPDefs.AbstractToken tok ) 30 | { 31 | return this.m_code == tok.m_code && this.param.same( ((ParamToken)tok).param ); 32 | } 33 | 34 | @Override 35 | public int length () 36 | { 37 | return this.param.symbol.length(); 38 | } 39 | 40 | @Override 41 | public void output ( final OutputStream out ) throws IOException 42 | { 43 | out.write(this.param.symbol.bytes); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/PreprOptions.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | public class PreprOptions implements IPreprOptions 4 | { 5 | private boolean m_noStdInc = false; 6 | private boolean m_gccExtensions = true; 7 | 8 | private boolean m_warnUndef = false; 9 | private int m_maxIncludeDepth = 256; 10 | 11 | @Override public boolean getNoStdInc () { return m_noStdInc; } 12 | @Override public boolean getGccExtensions () { return m_gccExtensions; } 13 | @Override public boolean getWarnUndef () { return m_warnUndef; } 14 | @Override public int getMaxIncludeDepth () { return m_maxIncludeDepth; } 15 | 16 | public void setNoStdInc ( boolean noStdInc ) { this.m_noStdInc = noStdInc; } 17 | public void setGccExtensions ( boolean gccExtensions ) { this.m_gccExtensions = gccExtensions; } 18 | public void setWarnUndef ( boolean warnUndef ) { this.m_warnUndef = warnUndef; } 19 | public void setMaxIncludeDepth ( int maxIncludeDepth ) { this.m_maxIncludeDepth = maxIncludeDepth; } 20 | } 21 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/SearchPathFactory.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import java.io.File; 4 | import java.util.HashMap; 5 | import java.util.Iterator; 6 | import java.util.LinkedHashSet; 7 | 8 | public class SearchPathFactory 9 | { 10 | private LinkedHashSet m_defSet = new LinkedHashSet(); 11 | private LinkedHashSet m_angledSet = new LinkedHashSet(); 12 | private LinkedHashSet m_quotedSet = new LinkedHashSet(); 13 | 14 | private final HashMap m_angledCache = new HashMap(); 15 | /** 16 | * Maps from "cur-directory:q-include-name" to Result 17 | */ 18 | private final HashMap m_quotedCache = new HashMap(); 19 | 20 | public void addDefaultInclude ( String path ) 21 | { 22 | assert path != null; 23 | m_defSet.add( new File(path) ); 24 | } 25 | 26 | public void addInclude ( String path ) 27 | { 28 | assert path != null; 29 | m_angledSet.add( new File(path) ); 30 | } 31 | 32 | public void addQuotedInclude ( String path ) 33 | { 34 | assert path != null; 35 | m_quotedSet.add( new File(path) ); 36 | } 37 | 38 | /** Must be invoked after all options have been parsed, to prepare the internal structures */ 39 | public ISearchPath finish ( IPreprOptions opts ) 40 | { 41 | if (opts.getNoStdInc()) 42 | m_defSet.clear(); 43 | else 44 | m_angledSet.removeAll( m_defSet ); 45 | 46 | // Remove all non-existent include directories to speed up the lookup later 47 | for (Iterator it = m_defSet.iterator(); it.hasNext(); ) 48 | { 49 | final File dirPath = it.next(); 50 | if (!dirPath.isDirectory()) 51 | it.remove(); 52 | } 53 | for (Iterator it = m_angledSet.iterator(); it.hasNext(); ) 54 | { 55 | final File dirPath = it.next(); 56 | if (!dirPath.isDirectory()) 57 | it.remove(); 58 | } 59 | 60 | return new ISearchPath(){ 61 | @Override 62 | public Result searchQuoted ( final String curFile, final String fileName ) 63 | { 64 | return _searchQuoted( curFile, new File(fileName) ); 65 | } 66 | 67 | @Override 68 | public Result searchAngled ( final String fileName ) 69 | { 70 | return _searchAngled( new File(fileName) ); 71 | } 72 | }; 73 | } 74 | 75 | private final ISearchPath.Result _searchQuoted ( final String curFile, final File fileName ) 76 | { 77 | if (fileName.isAbsolute()) 78 | return _searchAngled( fileName ); 79 | 80 | ISearchPath.Result res; 81 | final File curDir = new File(curFile).getParentFile(); 82 | final String key = (curDir != null ? curDir.getPath() : "") + File.pathSeparatorChar + fileName; 83 | 84 | if ( (res = m_quotedCache.get( key )) == null ) 85 | { 86 | File f = new File( curDir, fileName.getPath() ); 87 | if (!f.exists()) 88 | f = search( m_quotedSet, fileName.getPath() ); 89 | 90 | if (f != null) 91 | res = new ISearchPath.Result( f.getPath(), f.getAbsolutePath() ); 92 | else 93 | res = _searchAngled( fileName ); 94 | 95 | if (res != null) 96 | m_quotedCache.put( key, res ); 97 | } 98 | 99 | return res; 100 | } 101 | 102 | private final ISearchPath.Result _searchAngled ( final File fileName ) 103 | { 104 | ISearchPath.Result res; 105 | 106 | if ( (res = m_angledCache.get( fileName )) == null) 107 | { 108 | File f; 109 | 110 | if (fileName.isAbsolute()) 111 | { 112 | if (fileName.exists()) 113 | f = fileName; 114 | else 115 | f = null; 116 | } 117 | else if ( (f = search( m_angledSet, fileName.getPath() )) == null) 118 | f = search( m_defSet, fileName.getPath() ); 119 | 120 | if (f != null) 121 | m_angledCache.put( fileName, res = new ISearchPath.Result(f.getPath(), f.getAbsolutePath()) ); 122 | } 123 | 124 | return res; 125 | } 126 | 127 | private static File search ( LinkedHashSet set, String fileName ) 128 | { 129 | for ( File dir : set ) 130 | { 131 | File file = new File(dir, fileName); 132 | if (file.exists()) 133 | return file; 134 | } 135 | return null; 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /java/cpp/src/c99/parser/pp/TokenList.java: -------------------------------------------------------------------------------- 1 | package c99.parser.pp; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.util.Iterator; 6 | 7 | public class TokenList implements Iterable 8 | { 9 | private int m_size; 10 | 11 | private final PPLexer.AbstractToken m_head = new PPLexer.AbstractToken() 12 | { 13 | @SuppressWarnings("CloneDoesntCallSuperClone") 14 | @Override public PPLexer.AbstractToken clone () { return null; } 15 | @Override public boolean same ( final PPLexer.AbstractToken tok ) { return false; } 16 | @Override public int length () { return 0; } 17 | @Override public void output ( final OutputStream out ) throws IOException {} 18 | }; 19 | 20 | public TokenList () 21 | { 22 | m_head.m_prev = m_head.m_next = m_head; 23 | } 24 | 25 | public final int size () 26 | { 27 | return m_size; 28 | } 29 | 30 | public final boolean isEmpty () 31 | { 32 | // return m_head.m_next == m_head 33 | return m_size == 0; 34 | } 35 | 36 | @SuppressWarnings("unchecked") 37 | private final E cast ( PPLexer.AbstractToken t ) 38 | { 39 | return (E)t; 40 | } 41 | 42 | public final E first () 43 | { 44 | return m_head.m_next != m_head ? cast( m_head.m_next ) : null; 45 | } 46 | 47 | public final E last () 48 | { 49 | return cast(m_head.m_prev); 50 | } 51 | 52 | public final E next ( E elem ) 53 | { 54 | return elem.m_next != m_head ? cast(elem.m_next) : null; 55 | } 56 | 57 | public final void insertBefore ( E elem, PPLexer.AbstractToken before ) 58 | { 59 | assert elem.m_prev == null && elem.m_next == null; 60 | 61 | PPLexer.AbstractToken last = before.m_prev; 62 | elem.m_next = before; 63 | before.m_prev = elem; 64 | elem.m_prev = last; 65 | last.m_next = elem; 66 | 67 | ++m_size; 68 | } 69 | 70 | public final void addLast ( E elem ) 71 | { 72 | insertBefore( elem, m_head ); 73 | } 74 | 75 | public final void addLastClone ( E elem ) 76 | { 77 | insertBefore( cast(elem.clone()), m_head ); 78 | } 79 | 80 | public final void remove ( E elem ) 81 | { 82 | elem.m_prev.m_next = elem.m_next; 83 | elem.m_next.m_prev = elem.m_prev; 84 | elem.m_prev = elem.m_next = null; 85 | 86 | --m_size; 87 | } 88 | 89 | public final E removeFirst () 90 | { 91 | E elem = first(); 92 | remove( elem ); 93 | return elem; 94 | } 95 | 96 | public final E removeLast () 97 | { 98 | E elem = last(); 99 | remove( elem ); 100 | return elem; 101 | } 102 | 103 | public final void transferAllBefore ( TokenList fromList, PPLexer.AbstractToken before ) 104 | { 105 | if (fromList.isEmpty()) 106 | return; 107 | 108 | PPLexer.AbstractToken fhead = fromList.m_head; 109 | PPLexer.AbstractToken last = before.m_prev; 110 | fhead.m_prev.m_next = before; 111 | before.m_prev = fhead.m_prev; 112 | fhead.m_next.m_prev = last; 113 | last.m_next = fhead.m_next; 114 | 115 | fhead.m_prev = fhead.m_next = fhead; 116 | m_size += fromList.m_size; 117 | fromList.m_size = 0; 118 | } 119 | 120 | public final void transferAllBeforeFirst ( TokenList fromList ) 121 | { 122 | transferAllBefore( fromList, m_head.m_next ); 123 | } 124 | 125 | public final void transferAll ( TokenList fromList ) 126 | { 127 | transferAllBefore( fromList, m_head ); 128 | } 129 | 130 | public final void addAllClone ( TokenList fromList ) 131 | { 132 | final PPLexer.AbstractToken fhead = fromList.m_head; 133 | for ( PPLexer.AbstractToken cur = fhead.m_next; cur != fhead; cur = cur.m_next ) 134 | addLastClone( cast(cur) ); 135 | } 136 | 137 | public final String toString () 138 | { 139 | StringBuilder res = new StringBuilder(); 140 | res.append( "TokenList{" ); 141 | for ( PPLexer.AbstractToken cur = m_head.m_next; cur != m_head; cur = cur.m_next ) 142 | { 143 | if (cur != m_head.m_next) 144 | res.append( ", " ); 145 | res.append( cur.toString() ); 146 | } 147 | res.append( "}" ); 148 | return res.toString(); 149 | } 150 | 151 | @Override 152 | public Iterator iterator () 153 | { 154 | return new Iterator() 155 | { 156 | private PPLexer.AbstractToken m_cur = m_head.m_next; 157 | 158 | @Override 159 | public boolean hasNext () 160 | { 161 | return m_cur != m_head; 162 | } 163 | 164 | @Override 165 | public E next () 166 | { 167 | E res = cast(m_cur); 168 | m_cur = m_cur.m_next; 169 | return res; 170 | } 171 | 172 | @Override 173 | public void remove () 174 | { 175 | TokenList.this.remove( cast(m_cur.m_prev) ); 176 | } 177 | }; 178 | } 179 | } // class 180 | -------------------------------------------------------------------------------- /java/cpp/test/c99/ConstantTest.java: -------------------------------------------------------------------------------- 1 | package c99; 2 | 3 | import org.junit.Test; 4 | 5 | import static c99.Constant.makeLong; 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class ConstantTest 10 | { 11 | 12 | private void add ( long a, long b, long res, TypeSpec spec ) 13 | { 14 | Constant.IntC rc = Constant.newIntConstant( spec ); 15 | 16 | rc.add( makeLong( spec, a ), makeLong( spec, b ) ); 17 | assertEquals( "add", makeLong( spec, res ), rc ); 18 | } 19 | 20 | private void sub ( long a, long b, long res, TypeSpec spec ) 21 | { 22 | Constant.IntC rc = Constant.newIntConstant( spec ); 23 | 24 | rc.sub( makeLong( spec, a ), makeLong( spec, b ) ); 25 | assertEquals( "sub", makeLong( spec, res ), rc ); 26 | } 27 | 28 | private void shr ( long a, long b, long res, TypeSpec spec ) 29 | { 30 | Constant.IntC rc = Constant.newIntConstant( spec ); 31 | 32 | rc.shr( makeLong( spec, a ), makeLong( TypeSpec.UINT, b ) ); 33 | assertEquals( "shr", makeLong( spec, res ), rc ); 34 | } 35 | 36 | private void div ( long a, long b, long res, TypeSpec spec ) 37 | { 38 | Constant.IntC rc = Constant.newIntConstant( spec ); 39 | 40 | rc.div( makeLong( spec, a ), makeLong( spec, b ) ); 41 | assertEquals( "div", makeLong( spec, res ), rc ); 42 | } 43 | 44 | private void rem ( long a, long b, long res, TypeSpec spec ) 45 | { 46 | Constant.IntC rc = Constant.newIntConstant( spec ); 47 | 48 | rc.rem( makeLong( spec, a ), makeLong( spec, b ) ); 49 | assertEquals( "rem", makeLong( spec, res ), rc ); 50 | } 51 | 52 | @Test 53 | public void testNewConstant () throws Exception 54 | { 55 | add( 10, 20, 30, TypeSpec.UINT ); 56 | add( 10, 20, 30, TypeSpec.ULLONG ); 57 | add( 0xFFFFFFFFFFFFFFF0L, 0x01, 0xFFFFFFFFFFFFFFF1L, TypeSpec.ULLONG ); 58 | 59 | add( 255, 1, 0, TypeSpec.UCHAR ); 60 | sub( 0, 1, 255, TypeSpec.UCHAR ); 61 | 62 | add( 127, 1, -128, TypeSpec.SCHAR ); 63 | sub( 0, 1, -1, TypeSpec.SCHAR ); 64 | 65 | shr( 0xFFFFFFFFFFFFFFF0L, 0x04, 0x0FFFFFFFFFFFFFFFL, TypeSpec.ULLONG ); 66 | shr( 0xFFFFFFFFFFFFFFF0L, 0x04, 0xFFFFFFFFFFFFFFFFL, TypeSpec.SLLONG ); 67 | 68 | div( 0xFFFFFFFFFFFFFFF0L, 16, 0x0FFFFFFFFFFFFFFFL, TypeSpec.ULLONG ); 69 | rem( 0xFFFFFFFFFFFFFFF0L, 16, 0, TypeSpec.ULLONG ); 70 | 71 | div( 0xFFFFFFFFFFFFFFF1L, 16, 0x0FFFFFFFFFFFFFFFL, TypeSpec.ULLONG ); 72 | rem( 0xFFFFFFFFFFFFFFF1L, 16, 1, TypeSpec.ULLONG ); 73 | 74 | assertTrue( makeLong( TypeSpec.UINT, 10 ).eq( makeLong( TypeSpec.UINT, 10 ) ) ); 75 | assertTrue( makeLong( TypeSpec.UINT, 10 ).ne( makeLong( TypeSpec.UINT, 20 ) ) ); 76 | assertTrue( makeLong( TypeSpec.UINT, 10 ).lt( makeLong( TypeSpec.UINT, 20 ) ) ); 77 | assertTrue( makeLong( TypeSpec.UINT, 10 ).le( makeLong( TypeSpec.UINT, 20 ) ) ); 78 | assertTrue( makeLong( TypeSpec.UINT, 10 ).le( makeLong( TypeSpec.UINT, 10 ) ) ); 79 | assertTrue( makeLong( TypeSpec.UINT, 20 ).gt( makeLong( TypeSpec.UINT, 10 ) ) ); 80 | assertTrue( makeLong( TypeSpec.UINT, 20 ).ge( makeLong( TypeSpec.UINT, 10 ) ) ); 81 | assertTrue( makeLong( TypeSpec.UINT, 20 ).ge( makeLong( TypeSpec.UINT, 20 ) ) ); 82 | 83 | assertTrue( makeLong( TypeSpec.UINT, -1 ).gt( makeLong( TypeSpec.UINT, 1 ) ) ); 84 | assertTrue( makeLong( TypeSpec.SINT, -1 ).lt( makeLong( TypeSpec.SINT, 1 ) ) ); 85 | 86 | assertTrue( makeLong( TypeSpec.ULLONG, -1 ).gt( makeLong( TypeSpec.ULLONG, 1 ) ) ); 87 | assertTrue( makeLong( TypeSpec.SLLONG, -1 ).lt( makeLong( TypeSpec.SLLONG, 1 ) ) ); 88 | } 89 | } // class 90 | 91 | -------------------------------------------------------------------------------- /java/libs/hamcrest-core-1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/java/libs/hamcrest-core-1.3.jar -------------------------------------------------------------------------------- /java/libs/junit-4.11.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/java/libs/junit-4.11.jar -------------------------------------------------------------------------------- /parse.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | exec java -ea -jar ${0%/*}/java/out/artifacts/c99j_jar/c99j.jar $@ 3 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.run 2 | -------------------------------------------------------------------------------- /tests/decl/attr1.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | int __attribute__((x86far,x86near)) v1; 5 | int __attribute__((x86ds,x86cs)) v2; 6 | int __attribute__((x86ds,x86far)) v3; 7 | -------------------------------------------------------------------------------- /tests/decl/decl1.c: -------------------------------------------------------------------------------- 1 | // Just genetic santicy check 2 | int x; 3 | char x; 4 | 5 | int y, y; 6 | 7 | typedef int INT; 8 | int INT; 9 | 10 | int x = 0; 11 | int x = 0; -------------------------------------------------------------------------------- /tests/decl/decl1.c.msg: -------------------------------------------------------------------------------- 1 | decl1.c(3)[6..7]: error: 'x' redeclared differently; previous declaration here: decl1.c(2)[5..6] 2 | decl1.c(8)[5..8]: error: 'INT': invalid redeclaration; previously declared here: decl1.c(7)[13..16] 3 | decl1.c(11)[5..6]: error: 'x': invalid redefinition; already defined here: decl1.c(10)[5..6] 4 | -------------------------------------------------------------------------------- /tests/decl/decl10.c: -------------------------------------------------------------------------------- 1 | struct S 2 | { 3 | int a; 4 | int b[]; 5 | }; 6 | 7 | -------------------------------------------------------------------------------- /tests/decl/decl2.c: -------------------------------------------------------------------------------- 1 | // declaration specifiers failure cases 2 | 3 | #define TDUP(spec, other, name) spec other name; spec spec other name 4 | #define TDUP2(spec, other, name) spec other name; spec spec other name ## _1 5 | 6 | TDUP(const,int,v1); 7 | TDUP(signed,int,v2); 8 | TDUP(unsigned,int,v2__1); 9 | signed unsigned v2__2; 10 | TDUP(_Thread_local,int,v3); 11 | TDUP(_Complex,float,v3__1); 12 | TDUP(_Imaginary,float,v3__2); 13 | TDUP2(typedef,int,T1); 14 | typedef typedef typedef int T2; 15 | TDUP(extern,int,v4); 16 | TDUP(static,int,v5); 17 | 18 | void func ( void ) 19 | { 20 | TDUP2(auto,int,v6); 21 | TDUP2(register,int,v7); 22 | } 23 | 24 | typedef extern int x1; 25 | extern static int v10; 26 | extern static auto int v10_1; 27 | 28 | TDUP(_Bool,,v8); 29 | TDUP(char,,v9); 30 | TDUP(int,,v10); 31 | TDUP(void,*,v11); 32 | TDUP(float,,v12); 33 | TDUP(double,,v13); 34 | _Bool int v14; 35 | int char v15; 36 | float int v16; 37 | int float char v17; 38 | 39 | typedef int INT; 40 | 41 | TDUP(struct S1,,v18); 42 | struct S1 union S2 v19; 43 | // TODO: enum 44 | 45 | short v20; 46 | short short v21; 47 | short long v22; 48 | long v23; 49 | long long v24; 50 | long long long v26; 51 | long short long v27; 52 | short long long v28; 53 | long long short v29; 54 | 55 | _Complex v30; 56 | extern v31; 57 | 58 | #define TSL(base,name) \ 59 | base name; signed base name ## _si; unsigned base name ## __un; short base name ## _sh; long base name ## _lo 60 | 61 | TSL(_Bool,v32); 62 | TSL(void *,v33); 63 | TSL(float,v34); 64 | TSL(double,v35); 65 | TSL(struct S3,v36); 66 | TSL(union S4,v37); 67 | TSL(char,v38); 68 | -------------------------------------------------------------------------------- /tests/decl/decl2.c.msg: -------------------------------------------------------------------------------- 1 | decl2.c(7)[1..20]: error: More than one 'signed' specified 2 | decl2.c(8)[1..25]: error: More than one 'unsigned' specified 3 | decl2.c(9)[8..16]: error: Both 'unsigned' and 'signed' specified 4 | decl2.c(10)[1..27]: error: More than one '_Thread_local' specified 5 | decl2.c(11)[1..27]: error: More than one '_Complex' specified 6 | decl2.c(12)[1..29]: warning: _Imaginary is an extension 7 | decl2.c(12)[1..29]: warning: _Imaginary is an extension 8 | decl2.c(12)[1..29]: warning: _Imaginary is an extension 9 | decl2.c(12)[1..29]: error: More than one '_Imaginary' specified 10 | decl2.c(13)[1..22]: error: More than one 'typedef' specified 11 | decl2.c(14)[9..16]: error: More than one 'typedef' specified 12 | decl2.c(14)[17..24]: error: More than one 'typedef' specified 13 | decl2.c(15)[1..20]: error: More than one 'extern' specified 14 | decl2.c(16)[1..20]: error: More than one 'static' specified 15 | decl2.c(20)[3..21]: error: More than one 'auto' specified 16 | decl2.c(21)[3..25]: error: More than one 'register' specified 17 | decl2.c(24)[9..15]: error: Both 'extern' and 'typedef' specified 18 | decl2.c(25)[8..14]: error: Both 'static' and 'extern' specified 19 | decl2.c(26)[8..14]: error: Both 'static' and 'extern' specified 20 | decl2.c(26)[15..19]: error: Both 'auto' and 'extern' specified 21 | decl2.c(28)[1..16]: error: More than one '_Bool' specified 22 | decl2.c(29)[1..15]: error: More than one 'char' specified 23 | decl2.c(30)[1..15]: error: More than one 'int' specified 24 | decl2.c(31)[1..17]: error: More than one 'void' specified 25 | decl2.c(32)[1..17]: error: More than one 'float' specified 26 | decl2.c(33)[1..18]: error: More than one 'double' specified 27 | decl2.c(34)[7..10]: error: Both 'int' and '_Bool' specified 28 | decl2.c(35)[5..9]: error: Both 'char' and 'int' specified 29 | decl2.c(36)[7..10]: error: Both 'int' and 'float' specified 30 | decl2.c(37)[5..10]: error: Both 'float' and 'int' specified 31 | decl2.c(37)[11..15]: error: Both 'char' and 'int' specified 32 | decl2.c(41)[1..21]: error: More than one 'struct S1' specified 33 | decl2.c(42)[11..16]: error: Both 'union S2' and 'struct S1' specified 34 | decl2.c(46)[7..12]: error: More than one 'short' specified 35 | decl2.c(47)[7..11]: error: Both 'long' and 'short' specified 36 | decl2.c(50)[11..15]: error: Both 'long' and 'long long' specified 37 | decl2.c(51)[6..11]: error: Both 'short' and 'long' specified 38 | decl2.c(52)[7..11]: error: Both 'long' and 'short' specified 39 | decl2.c(52)[12..16]: error: Both 'long' and 'short' specified 40 | decl2.c(53)[11..16]: error: Both 'short' and 'long long' specified 41 | decl2.c(55)[1..9]: warning: implicit 'double' assumed with '_Complex' 42 | decl2.c(56)[1..7]: warning: implicit 'int' assumed 43 | decl2.c(61)[1..15]: error: Both 'signed' and '_Bool' specified 44 | decl2.c(61)[1..15]: error: Both 'unsigned' and '_Bool' specified 45 | decl2.c(61)[1..15]: error: Both 'short' and '_Bool' specified 46 | decl2.c(61)[1..15]: error: Both 'long' and '_Bool' specified 47 | decl2.c(62)[1..16]: error: Both 'signed' and 'void' specified 48 | decl2.c(62)[1..16]: error: Both 'unsigned' and 'void' specified 49 | decl2.c(62)[1..16]: error: Both 'short' and 'void' specified 50 | decl2.c(62)[1..16]: error: Both 'long' and 'void' specified 51 | decl2.c(63)[1..15]: error: Both 'signed' and 'float' specified 52 | decl2.c(63)[1..15]: error: Both 'unsigned' and 'float' specified 53 | decl2.c(63)[1..15]: error: Both 'short' and 'float' specified 54 | decl2.c(63)[1..15]: error: Both 'long' and 'float' specified 55 | decl2.c(64)[1..16]: error: Both 'signed' and 'double' specified 56 | decl2.c(64)[1..16]: error: Both 'unsigned' and 'double' specified 57 | decl2.c(64)[1..16]: error: Both 'short' and 'double' specified 58 | decl2.c(65)[1..19]: error: Both 'signed' and 'struct S3' specified 59 | decl2.c(65)[1..19]: error: Both 'unsigned' and 'struct S3' specified 60 | decl2.c(65)[1..19]: error: Both 'short' and 'struct S3' specified 61 | decl2.c(65)[1..19]: error: Both 'long' and 'struct S3' specified 62 | decl2.c(66)[1..18]: error: Both 'signed' and 'union S4' specified 63 | decl2.c(66)[1..18]: error: Both 'unsigned' and 'union S4' specified 64 | decl2.c(66)[1..18]: error: Both 'short' and 'union S4' specified 65 | decl2.c(66)[1..18]: error: Both 'long' and 'union S4' specified 66 | decl2.c(67)[1..14]: error: Both 'short' and 'char' specified 67 | decl2.c(67)[1..14]: error: Both 'long' and 'char' specified 68 | -------------------------------------------------------------------------------- /tests/decl/decl3.c: -------------------------------------------------------------------------------- 1 | // Declarator failure cases 2 | 3 | int a1[10]; 4 | int a2[const 10]; 5 | int a3[static 10]; 6 | int a4[*]; 7 | 8 | void func1 ( int p1[10], 9 | int p2[const 10], // FAIL! 10 | int p3[static 10], // FAIL! 11 | int p4[*] ) // FAIL! 12 | { 13 | int b1[10]; 14 | int b2[const 10]; 15 | int b3[static 10]; 16 | int b4[*]; 17 | } 18 | 19 | void func2 ( a, b, c ); 20 | void func3 ( a, b, a, c ); 21 | 22 | -------------------------------------------------------------------------------- /tests/decl/decl3.c.msg: -------------------------------------------------------------------------------- 1 | decl3.c(4)[8..13]: error: type qualifiers in non-parameter array declarator 2 | decl3.c(5)[8..14]: error: 'static' in non-parameter array declarator 3 | decl3.c(6)[8..9]: error: '[*]' in non-parameter array declarator 4 | decl3.c(14)[10..15]: error: type qualifiers in non-parameter array declarator 5 | decl3.c(15)[10..16]: error: 'static' in non-parameter array declarator 6 | decl3.c(16)[10..11]: error: '[*]' in non-parameter array declarator 7 | decl3.c(20)[20..21]: error: parameter 'a' already declared here: decl3.c(20)[14..15] 8 | -------------------------------------------------------------------------------- /tests/decl/decl4.c: -------------------------------------------------------------------------------- 1 | // Declaration faulure cases 2 | 3 | int v1; 4 | register int v2; 5 | auto int v3; 6 | 7 | extern int v4 = 0; 8 | 9 | void func1 ( void ) 10 | { 11 | extern int v5; 12 | extern int v6 = 0; 13 | } 14 | 15 | void func2 ( 16 | register p1, 17 | auto int p2, 18 | static int p3 19 | ); 20 | 21 | struct S1 22 | { 23 | int f1; 24 | static int f2; 25 | int f3[]; 26 | }; 27 | 28 | int v7; 29 | char v7; 30 | 31 | char const * v8; 32 | char const * v8; 33 | char const * const v8; 34 | 35 | int v9; 36 | int v9; 37 | int v9 = 1; 38 | int v9 = 2; 39 | int v9; 40 | static int v9; 41 | 42 | int v10; 43 | 44 | void func3 ( void ) 45 | { 46 | extern char v10; 47 | } 48 | 49 | int v11; 50 | void func4 ( void ) 51 | { 52 | extern int v11; 53 | int v11; 54 | } 55 | 56 | int v12; 57 | static int v12; 58 | 59 | static int v13 = 0; 60 | extern int v13; -------------------------------------------------------------------------------- /tests/decl/decl4.c.msg: -------------------------------------------------------------------------------- 1 | decl4.c(4)[1..9]: error: 'register' storage class at file scope 2 | decl4.c(5)[1..5]: error: 'auto' storage class at file scope 3 | decl4.c(7)[12..14]: warning: 'v4': ignoring 'extern' in initialization 4 | decl4.c(12)[14..16]: error: 'v6': 'extern' and initialization 5 | decl4.c(16)[3..11]: warning: implicit 'int' assumed 6 | decl4.c(16)[3..11]: warning: 'register' storage class is ignored 7 | decl4.c(17)[3..7]: error: 'auto' storage class in function declaration 8 | decl4.c(18)[3..9]: error: 'static' storage class in function declaration 9 | decl4.c(24)[3..9]: error: storage class in struct/union scope 10 | decl4.c(25)[7..9]: error: 'f3' has an incomplete type 11 | decl4.c(29)[6..8]: error: 'v7' redeclared differently; previous declaration here: decl4.c(28)[5..7] 12 | decl4.c(33)[20..22]: error: 'v8' redeclared differently; previous declaration here: decl4.c(31)[14..16] 13 | decl4.c(38)[5..7]: error: 'v9': invalid redefinition; already defined here: decl4.c(37)[5..7] 14 | decl4.c(40)[12..14]: error: 'v9': invalid redeclaration; previously declared here: decl4.c(37)[5..7] 15 | decl4.c(46)[15..18]: error: 'v10' redeclared differently; previous declaration here: decl4.c(42)[5..8] 16 | decl4.c(53)[7..10]: error: 'v11': invalid redeclaration; previously declared here: decl4.c(52)[14..17] 17 | decl4.c(57)[12..15]: error: 'v12': invalid redeclaration; previously declared here: decl4.c(56)[5..8] 18 | -------------------------------------------------------------------------------- /tests/decl/decl5.c: -------------------------------------------------------------------------------- 1 | // tag failure cases 2 | 3 | struct S1; 4 | struct S1 5 | { 6 | int x, y; 7 | }; 8 | 9 | struct S2 10 | { 11 | int x; 12 | }; 13 | struct S2 * v1; 14 | struct S2 15 | { 16 | int x; 17 | }; 18 | 19 | struct S3 20 | { 21 | int y; 22 | }; 23 | 24 | union S3 25 | { 26 | int y; 27 | }; 28 | 29 | struct S4; 30 | union S4; -------------------------------------------------------------------------------- /tests/decl/decl5.c.msg: -------------------------------------------------------------------------------- 1 | decl5.c(14)[8..10]: error: redefinition of 'struct S2'. originally defined here: decl5.c(9)[8..10] 2 | decl5.c(24)[7..9]: error: 'union S3' previously defined as a different kind of tag here: decl5.c(19)[8..10] 3 | decl5.c(30)[7..9]: error: 'union S4' previously defined as a different kind of tag here: decl5.c(29)[8..10] 4 | -------------------------------------------------------------------------------- /tests/decl/decl6.c: -------------------------------------------------------------------------------- 1 | struct X {int x;}; 2 | 3 | // FAIL: This should be a warning! 4 | void func ( union X { int x; } y ); 5 | 6 | void func3 ( union X { int x; } y, struct X { int x; } z ); 7 | 8 | void func1 ( int p1[10], 9 | int p2[const 10], // FAIL! 10 | int p3[static 10], // FAIL! 11 | int p4[*] ) // FAIL! 12 | { 13 | } 14 | 15 | // This should compile, albeit with a warning 16 | void func2 ( struct SS { int a; } x, struct SS y ) 17 | { 18 | } 19 | 20 | void func5 ( struct S5 * p ); 21 | -------------------------------------------------------------------------------- /tests/decl/decl6.c.msg: -------------------------------------------------------------------------------- 1 | decl6.c(4)[19..20]: warning: declaration of 'union X' will not be visible outside of the function 2 | decl6.c(6)[20..21]: warning: declaration of 'union X' will not be visible outside of the function 3 | decl6.c(6)[43..44]: error: 'struct X' previously defined as a different kind of tag here: decl6.c(6)[20..21] 4 | decl6.c(6)[43..44]: warning: declaration of 'struct' will not be visible outside of the function 5 | decl6.c(16)[21..23]: warning: declaration of 'struct SS' will not be visible outside of the function 6 | decl6.c(20)[21..23]: warning: declaration of 'struct S5' will not be visible outside of the function 7 | -------------------------------------------------------------------------------- /tests/decl/decl7.c: -------------------------------------------------------------------------------- 1 | struct S1 func1 ( void ); 2 | 3 | int (func2 ( void ))[10]; //BAD: function returning array 4 | 5 | typedef void FUNC1 ( void ); 6 | FUNC1 funcs2[10]; //BAD: array of functions 7 | 8 | FUNC1 func3 ( void ); //BAD: function returning a function 9 | 10 | void (func4 ( void ))(void); 11 | 12 | struct S1 func1 ( void ) //BAD: incomplete type in function definition 13 | {} 14 | 15 | struct S2 16 | { 17 | void func1 ( void ); //BAD: field declared as function 18 | }; 19 | 20 | void (*funcs3[10])(void); 21 | void (funcs1[10])(void); //BAD: array of functions 22 | -------------------------------------------------------------------------------- /tests/decl/decl7.c.msg: -------------------------------------------------------------------------------- 1 | decl7.c(3)[12..20]: error: function returning an array 2 | decl7.c(6)[13..17]: error: array of functions 3 | decl7.c(8)[13..21]: error: function returning a function 4 | decl7.c(10)[13..21]: error: function returning a function 5 | decl7.c(17)[10..15]: error: field declared as a function in struct/union 6 | decl7.c(17)[10..15]: error: 'func1' has an incomplete type 7 | decl7.c(20)[13..14]: error: syntax error, unexpected [, expecting ( or ) 8 | -------------------------------------------------------------------------------- /tests/decl/decl8.c: -------------------------------------------------------------------------------- 1 | struct X 2 | { 3 | struct S { int s;} a; 4 | 5 | struct S m2[5]; 6 | } x[1]; 7 | 8 | struct S b[10]; 9 | 10 | struct Y 11 | { 12 | struct P { int p;}; 13 | struct P m2[5]; 14 | } y[1]; 15 | 16 | struct P c[10]; 17 | -------------------------------------------------------------------------------- /tests/decl/decl9.c: -------------------------------------------------------------------------------- 1 | struct S 2 | { 3 | int b; 4 | struct S * p; // This must not be a forward declaration 5 | }; 6 | 7 | 8 | void func1 ( void ) 9 | { 10 | int a = 1; 11 | { 12 | int a = 2, b = a; 13 | assert( b == 2 ); 14 | } 15 | { 16 | int a = a; // undefined value 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/decl/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | app=../../parse.sh 4 | 5 | for tst in *.c; do 6 | echo "Testing $tst" 7 | $app $tst 2>$tst.msg.run 8 | if diff -q -a $tst.msg $tst.msg.run > /dev/null; then 9 | rm $tst.msg.run 10 | else 11 | diff -y -a $tst.msg $tst.msg.run | less -S 12 | fi 13 | done 14 | -------------------------------------------------------------------------------- /tests/parser/asm1.c: -------------------------------------------------------------------------------- 1 | #define asm __asm__ 2 | 3 | asm("nop"); 4 | 5 | static inline int add ( int a, int b ) 6 | { 7 | int res = a; 8 | asm ("addl %[var],%0" : "+r" (res) : [var] "r" (b)); 9 | return res; 10 | } 11 | 12 | int func ( int a, int b ) 13 | { 14 | return add(a, b)+1; 15 | } -------------------------------------------------------------------------------- /tests/parser/asm2.c: -------------------------------------------------------------------------------- 1 | #define asm __asm__ 2 | 3 | int x asm("myvar") = 100; 4 | 5 | 6 | int func ( void ) asm("myfunc"); 7 | int func ( void ) 8 | { 9 | register int * foo asm("%edx") = 0; 10 | return *foo; 11 | } 12 | -------------------------------------------------------------------------------- /tests/parser/attr1.c: -------------------------------------------------------------------------------- 1 | int __attribute__((x86far(1))) x1; 2 | int __attribute__((x86far)) x2; 3 | int __attribute__(("x86far")) x3; 4 | int __attribute__(("__x86far__")) x3; 5 | int __attribute__((__x86far__)) x4; 6 | 7 | #define far __attribute__((x86far)) 8 | #define cdecl __attribute__((cdecl)) 9 | 10 | 11 | int far * ptr; 12 | void far cdecl strlen ( void ); 13 | 14 | int far f1; 15 | int f1; 16 | -------------------------------------------------------------------------------- /tests/parser/badf1.c: -------------------------------------------------------------------------------- 1 | int (*func)(); 2 | 3 | -------------------------------------------------------------------------------- /tests/parser/badf2.c: -------------------------------------------------------------------------------- 1 | int (a)(int x) 2 | { 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /tests/parser/badf3.c: -------------------------------------------------------------------------------- 1 | void (*signal(int sig))(int) 2 | { 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /tests/parser/badf4.c: -------------------------------------------------------------------------------- 1 | int (func) ( void ) (void) 2 | { 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /tests/parser/badf5.c: -------------------------------------------------------------------------------- 1 | void (*signal(int sig)) 2 | { 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /tests/parser/badfunc.c: -------------------------------------------------------------------------------- 1 | typedef int TYP; 2 | 3 | // error: TYP is interpreted as a type declaring an anonymous parameter 4 | // to an anynymous function. It is equivalent to 5 | // "int p1 ( int fn (TYP p) )" 6 | int bad1 ( int (TYP) ) 7 | { 8 | return TYP; 9 | } 10 | 11 | int good1 ( void ) 12 | { 13 | // Unlike the case with bad1, (TYP) is parsed simply as an 14 | // identifier surrounded by parentheses. It is equivalent to 15 | // "int TYP" 16 | int (TYP) = 0; 17 | return TYP; 18 | } 19 | 20 | // error: TYP is interpreted as a type, declaring an anonymous 21 | // parameter to an anonymous function. It is equivalent to 22 | // "void p ( int fn (TYP p) (void ) )"; 23 | void bad2 ( int (TYP) ( void ) ); 24 | 25 | void good2 () 26 | { 27 | // Unlike the case with bad2, (TYP) is parsed simply as an 28 | // identifier surrounded by parenthises. It is equivalent to 29 | // "int TYP ( void )" 30 | int (TYP) ( void ); 31 | TYP(); 32 | }; 33 | -------------------------------------------------------------------------------- /tests/parser/crash1.c: -------------------------------------------------------------------------------- 1 | int x;; 2 | -------------------------------------------------------------------------------- /tests/parser/parse1.c: -------------------------------------------------------------------------------- 1 | void func1 () 2 | {} 3 | 4 | void func2 ( void ) 5 | { 6 | int x; 7 | } 8 | -------------------------------------------------------------------------------- /tests/parser/parse2.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | void func ( void ) 4 | { 5 | }; 6 | -------------------------------------------------------------------------------- /tests/pp/a\nb.c: -------------------------------------------------------------------------------- 1 | __FILE__ 2 | __FILE__ 3 | 4 | -------------------------------------------------------------------------------- /tests/pp/a\nb.c.i: -------------------------------------------------------------------------------- 1 | # 1 "a\\nb.c" 2 | "a\\nb.c" 3 | "a\\nb.c" 4 | 5 | -------------------------------------------------------------------------------- /tests/pp/a\nb.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/a\nb.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-comment-1.c: -------------------------------------------------------------------------------- 1 | /* hello */ 1 2 3 /* hello 2 ****/ 3 4 2 | // /* 3 | a b /* yep 4 | yep */ c d; 5 | a /* hello 6 | ds 7 | sdds 8 | -------------------------------------------------------------------------------- /tests/pp/pp-comment-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-comment-1.c" 2 | 1 2 3 3 4 3 | 4 | a b 5 | c d; 6 | a 7 | 8 | 9 | -------------------------------------------------------------------------------- /tests/pp/pp-comment-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-comment-1.c(5)[3]..(8)[1]: error: Unterminated block comment 2 | -------------------------------------------------------------------------------- /tests/pp/pp-const-1.c: -------------------------------------------------------------------------------- 1 | 'a' 2 | 'ab' 3 | 'abcde' 4 | 'abc\ 5 | def' 6 | 7 | 'ab 8 | 'xx' 9 | 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbb' 10 | 11 | '\x' 12 | '\x12345+' 13 | '\777' 14 | '\p' 15 | -------------------------------------------------------------------------------- /tests/pp/pp-const-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-const-1.c" 2 | 'a' 3 | 'ab' 4 | 'abcde' 5 | 'abcdef' 6 | 7 | 8 | 'ab 9 | 'xx' 10 | 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbb' 11 | 12 | '\x' 13 | '\x12345+' 14 | '\777' 15 | '\p' 16 | -------------------------------------------------------------------------------- /tests/pp/pp-const-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-const-1.c(2)[1..5]: warning: Multi-character character constant 2 | pp-const-1.c(3)[1..8]: error: Character constant is too long for its type 3 | pp-const-1.c(4)[1]..(5)[5]: error: Character constant is too long for its type 4 | pp-const-1.c(7)[1..4]: error: Unterminated character constant 5 | pp-const-1.c(7)[1..4]: warning: Multi-character character constant 6 | pp-const-1.c(8)[1..5]: warning: Multi-character character constant 7 | pp-const-1.c(9)[1..86]: error: Character constant is too long for its type 8 | pp-const-1.c(11)[2..5]: error: Invalid hex escape sequence in character constant 9 | pp-const-1.c(12)[4..9]: error: Integer overflow in character constant 10 | pp-const-1.c(12)[1..11]: warning: Multi-character character constant 11 | pp-const-1.c(13)[3..6]: error: Character overflow in character constant 12 | pp-const-1.c(14)[2..4]: error: Invalid escape sequence in character constant 13 | -------------------------------------------------------------------------------- /tests/pp/pp-const-2.c: -------------------------------------------------------------------------------- 1 | "a" 2 | "ab" 3 | "abcde" 4 | "abc\ 5 | def" 6 | 7 | "ab 8 | "xx" 9 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbb" 10 | 11 | "\x" 12 | "\x12345+" 13 | "\777" 14 | "\p" 15 | -------------------------------------------------------------------------------- /tests/pp/pp-const-2.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-const-2.c" 2 | "a" 3 | "ab" 4 | "abcde" 5 | "abcdef" 6 | 7 | 8 | "ab 9 | "xx" 10 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbb" 11 | 12 | "\x" 13 | "\x12345+" 14 | "\777" 15 | "\p" 16 | -------------------------------------------------------------------------------- /tests/pp/pp-const-2.c.msg: -------------------------------------------------------------------------------- 1 | pp-const-2.c(7)[1..4]: error: Unterminated string constant 2 | pp-const-2.c(11)[2..5]: error: Invalid hex escape sequence in string constant 3 | pp-const-2.c(12)[4..9]: error: Integer overflow in string constant 4 | pp-const-2.c(13)[3..6]: error: Character overflow in string constant 5 | pp-const-2.c(14)[2..4]: error: Invalid escape sequence in string constant 6 | -------------------------------------------------------------------------------- /tests/pp/pp-def-1.c: -------------------------------------------------------------------------------- 1 | #define MAX_COUNT 100 2 | #define MAX_COUNT 100 3 | #define MAX_COUNT 200 4 | 5 | #define BAD1( 6 | #define BAD2(+ 7 | #define BAD3(a, 8 | #define BAD4(... 9 | #define BAD5(a,a) 10 | #define GOOD5(a,b) (a)+(b) 11 | 12 | #define BAD6 ## 13 | #define BAD7 a ## 14 | #define GOOD7(a) a ## 1 15 | 16 | #define BAD8 # p 17 | #define GOOD8(p) # p 18 | 19 | #define BAD9(p) __VA_ARGS__ 20 | #define GOOD9(p,...) printf( p, __VA_ARGS__ ) 21 | -------------------------------------------------------------------------------- /tests/pp/pp-def-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-1.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/pp/pp-def-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-def-1.c(3)[9..18]: warning: redefinition of macro 'MAX_COUNT' differs from previous definition at pp-def-1.c(2)[9..18] 2 | pp-def-1.c(5)[14]..(6)[1]: error: Missing closing ')' in macro parameter list 3 | pp-def-1.c(6)[14..15]: error: Macro parameter name expected 4 | pp-def-1.c(7)[16]..(8)[1]: error: Missing closing ')' in macro parameter list 5 | pp-def-1.c(8)[17]..(9)[1]: error: Expected ')' after '...' in macro parameter list 6 | pp-def-1.c(9)[16..17]: error: Duplicated macro parameter 'a' 7 | pp-def-1.c(12)[14..16]: error: '##' can only occur between two tokens 8 | pp-def-1.c(13)[16..18]: error: '##' can only occur between two tokens 9 | pp-def-1.c(16)[16..17]: error: '#' must be followed by a macro parameter 10 | pp-def-1.c(19)[18..29]: error: '__VA_ARGS__' must only appear in a variadic macro 11 | -------------------------------------------------------------------------------- /tests/pp/pp-def-10.c: -------------------------------------------------------------------------------- 1 | #define PAR (x) 2 | #define NEG(x) (-(x)) 3 | #define MM(p) NEG p 4 | #define MMM(p) p 5 | #define TT NEG PAR 6 | 7 | NEG(x) 8 | NEG PAR 9 | MM(PAR) 10 | MMM( NEG PAR ) 11 | TT 12 | -------------------------------------------------------------------------------- /tests/pp/pp-def-10.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-10.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | (-(x)) 9 | NEG (x) 10 | (-(x)) 11 | (-(x)) 12 | NEG (x) 13 | -------------------------------------------------------------------------------- /tests/pp/pp-def-10.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-def-10.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-def-2.c: -------------------------------------------------------------------------------- 1 | #define THREE 3+ /*yeah*/ 2 2 | 3 | THREE,THREE,THR\ 4 | EE 5 | THREE 6 | -------------------------------------------------------------------------------- /tests/pp/pp-def-2.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-2.c" 2 | 3 | 4 | 3+ 2,3+ 2,3+ 2 5 | 6 | 3+ 2 7 | -------------------------------------------------------------------------------- /tests/pp/pp-def-2.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-def-2.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-def-3.c: -------------------------------------------------------------------------------- 1 | #define VOIDM() callFunc() 2 | 3 | VOIDM() 4 | 5 | #define FUNC_LIKE(a,b) ((a)+(b)) 6 | FUNC_LIKE 7 | FUNC_LIKE(1,2) 8 | 9 | 10 | VOIDM(, 11 | 12 | 13 | a() 14 | -------------------------------------------------------------------------------- /tests/pp/pp-def-3.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-3.c" 2 | 3 | 4 | callFunc() 5 | 6 | 7 | FUNC_LIKE 8 | ((1)+(2)) 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/pp/pp-def-3.c.msg: -------------------------------------------------------------------------------- 1 | pp-def-3.c(14)[1]: error: Unterminated argument list for macro 'VOIDM' 2 | -------------------------------------------------------------------------------- /tests/pp/pp-def-4.c: -------------------------------------------------------------------------------- 1 | #define INC(x) ((x)+1) 2 | INC( a b + c ) 3 | 4 | #define ADD(a,b) ( ( a ) + ( b ) ) 5 | 6 | ADD( 1+2, 3+a ) 7 | 8 | #define DOSTR(x) \ 9 | printf("%s\n", #x);\ 10 | x 11 | 12 | DOSTR( a ) 13 | DOSTR( exit(1) ); 14 | DOSTR( printf( "Hello\n" ) ); 15 | DOSTR(); 16 | -------------------------------------------------------------------------------- /tests/pp/pp-def-4.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-4.c" 2 | 3 | ((a b + c)+1) 4 | 5 | 6 | 7 | ( ( 1+2 ) + ( 3+a ) ) 8 | 9 | 10 | 11 | 12 | 13 | printf("%s\n", "a"); a 14 | printf("%s\n", "exit(1)"); exit(1); 15 | printf("%s\n", "printf( \"Hello\\n\" )"); printf( "Hello\n" ); 16 | printf("%s\n", ""); ; 17 | -------------------------------------------------------------------------------- /tests/pp/pp-def-4.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-def-4.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-def-5.c: -------------------------------------------------------------------------------- 1 | #define C1(a) a ## 1 + ## = 10; 2 | 3 | C1(var) 4 | C1(10.1) 5 | C1(-) 6 | C1("aa") -------------------------------------------------------------------------------- /tests/pp/pp-def-5.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-5.c" 2 | 3 | 4 | var1 += 10; 5 | 10.11 += 10; 6 | -1 += 10; 7 | "aa"1 += 10; -------------------------------------------------------------------------------- /tests/pp/pp-def-5.c.msg: -------------------------------------------------------------------------------- 1 | pp-def-5.c(5)[1..6]: error: Combining "-" and "1" does not produce a valid token 2 | pp-def-5.c(6)[1..9]: error: Combining ""aa"" and "1" does not produce a valid token 3 | -------------------------------------------------------------------------------- /tests/pp/pp-def-6.c: -------------------------------------------------------------------------------- 1 | #define LOG( sev, ... ) \ 2 | printf( #sev ": " ); \ 3 | printf( __VA_ARGS__ ) 4 | 5 | 6 | LOG( warn, "Error" ); 7 | LOG( err, "errno %d", errno ); 8 | LOG( info, "value %d=%d", valIndex-1, value+1 ); 9 | LOG( err ); 10 | 11 | #define LOG2( sev, fmt, ... ) \ 12 | printf( #sev ": " fmt "\n", ## __VA_ARGS__ ) 13 | 14 | LOG2( err, "errno %d", errno ); 15 | LOG2( err, "badbad", ); 16 | LOG2( err, "error" ); 17 | 18 | #define LOG3( sev, fmt, args... ) \ 19 | printf( #sev ": " fmt "\n", ## args ) 20 | 21 | LOG3( err3, "errno %d", errno ); 22 | LOG3( err3, "badbad", ); 23 | LOG3( err3, "error" ); 24 | -------------------------------------------------------------------------------- /tests/pp/pp-def-6.c.i: -------------------------------------------------------------------------------- 1 | # 3 "pp-def-6.c" 2 | 3 | 4 | 5 | printf( "warn" ": " ); printf( "Error" ); 6 | printf( "err" ": " ); printf( "errno %d", errno ); 7 | printf( "info" ": " ); printf( "value %d=%d", valIndex-1, value+1 ); 8 | printf( "err" ": " ); printf( ); 9 | 10 | 11 | 12 | 13 | printf( "err" ": " "errno %d" "\n", errno ); 14 | printf( "err" ": " "badbad" "\n", ); 15 | printf( "err" ": " "error" "\n" ); 16 | 17 | 18 | 19 | 20 | printf( "err3" ": " "errno %d" "\n", errno ); 21 | printf( "err3" ": " "badbad" "\n", ); 22 | printf( "err3" ": " "error" "\n" ); 23 | -------------------------------------------------------------------------------- /tests/pp/pp-def-6.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-def-6.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-def-7.c: -------------------------------------------------------------------------------- 1 | #define NEG(x) (-(x)) 2 | #define ABS(x) ((x) < 0 ? NEG(x) : (x)) 3 | 4 | ABS(1+a); 5 | 6 | #define f(a) a*g 7 | #define g(a) f(a) 8 | 9 | f(2) (9) 10 | 11 | #define REC(x) x+REC(x-1) 12 | 13 | REC(10); REC(11); 14 | 15 | NEG(NEG(1)); 16 | NEG(ABS(NEG(1))); 17 | 18 | #define RR( x ) x + RR 19 | 20 | RR(1); 21 | RR(2)(3); 22 | 23 | #define RR2 1 + RR2 24 | #define MM(x) x 25 | 26 | RR2; 27 | MM(RR2); 28 | 29 | #define M1 "M1"+M2 30 | #define M2 "M2"+M1 31 | 32 | M1 33 | M2 34 | -------------------------------------------------------------------------------- /tests/pp/pp-def-7.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-7.c" 2 | 3 | 4 | 5 | ((1+a) < 0 ? (-(1+a)) : (1+a)); 6 | 7 | 8 | 9 | 10 | 2*9*g 11 | 12 | 13 | 14 | 10+REC(10-1); 11+REC(11-1); 15 | 16 | (-((-(1)))); 17 | (-((((-(1))) < 0 ? (-((-(1)))) : ((-(1)))))); 18 | 19 | 20 | 21 | 1 + RR; 22 | 2 + RR(3); 23 | 24 | 25 | 26 | 27 | 1 + RR2; 28 | 1 + RR2; 29 | 30 | 31 | 32 | 33 | "M1"+"M2"+M1 34 | "M2"+"M1"+M2 35 | -------------------------------------------------------------------------------- /tests/pp/pp-def-7.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-def-7.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-def-8.c: -------------------------------------------------------------------------------- 1 | __FILE__ __LINE__ __DATE__ 2 | 3 | #define __LINE__ 10 4 | #define __FILE__ 20 5 | 6 | __FILE__ __LINE__ __DATE__ 7 | -------------------------------------------------------------------------------- /tests/pp/pp-def-8.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-8.c" 2 | "pp-def-8.c" 1 "Jul 13 2014" 3 | 4 | 5 | 6 | 7 | 20 10 "Jul 13 2014" 8 | -------------------------------------------------------------------------------- /tests/pp/pp-def-8.c.msg: -------------------------------------------------------------------------------- 1 | pp-def-8.c(3)[9..17]: warning: redefinition of builtin macro '__LINE__' 2 | pp-def-8.c(4)[9..17]: warning: redefinition of builtin macro '__FILE__' 3 | -------------------------------------------------------------------------------- /tests/pp/pp-def-9.c: -------------------------------------------------------------------------------- 1 | #define CAT2(a,b) a ## b 2 | #define CAT(a,b) CAT2(a, b ) 3 | 4 | CAT2( x, __LINE__ ); 5 | CAT( y, __LINE__ ); 6 | 7 | 8 | -------------------------------------------------------------------------------- /tests/pp/pp-def-9.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-def-9.c" 2 | 3 | 4 | 5 | x__LINE__; 6 | y5; 7 | 8 | 9 | -------------------------------------------------------------------------------- /tests/pp/pp-def-9.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-def-9.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-dir-1.c: -------------------------------------------------------------------------------- 1 | # x 2 | # y z 3 | # ++ 4 | -------------------------------------------------------------------------------- /tests/pp/pp-dir-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-dir-1.c" 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tests/pp/pp-dir-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-dir-1.c(1)[3..4]: error: Invalid preprocessor directive #x 2 | pp-dir-1.c(2)[3..4]: error: Invalid preprocessor directive #y 3 | pp-dir-1.c(3)[3..5]: error: Invalid preprocessor directive #++ 4 | -------------------------------------------------------------------------------- /tests/pp/pp-elif-1.c: -------------------------------------------------------------------------------- 1 | #if 1 2 | yes1; 3 | #elif 1 4 | no1 a; 5 | #elif 0 6 | no1 b; 7 | #else 8 | no1 c; 9 | #endif 10 | 11 | #if 0 12 | no2 a; 13 | #elif 1 14 | yes2; 15 | #elif 1 16 | no2 b; 17 | #else 18 | no3 c; 19 | #endif 20 | 21 | #if 0 22 | no3 a; 23 | #elif 0 24 | no3 b; 25 | #else 26 | yes3; 27 | #endif 28 | 29 | #if 0 30 | no4 a; 31 | #elif 0 32 | no4 b; 33 | #elif 1 34 | yes4; 35 | #else 36 | no4 c; 37 | #endif 38 | -------------------------------------------------------------------------------- /tests/pp/pp-elif-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-elif-1.c" 2 | 3 | yes1; 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | yes2; 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | yes3; 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | yes4; 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/pp/pp-elif-1.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-elif-1.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-error-1.c: -------------------------------------------------------------------------------- 1 | #pragma 2 | #pragma 1 2 3 | 4 | #error "This is my error" 5 | #error This is /*a */ another error 2 -------------------------------------------------------------------------------- /tests/pp/pp-error-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-error-1.c" 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/pp/pp-error-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-error-1.c(1)[2..8]: warning: Ignoring unsupported #pragma 2 | pp-error-1.c(2)[2..8]: warning: Ignoring unsupported #pragma 3 | pp-error-1.c(4)[26]..(5)[1]: error: #error "This is my error" 4 | pp-error-1.c(5)[1]: error: #error This is another error 2 5 | -------------------------------------------------------------------------------- /tests/pp/pp-gen-1.c: -------------------------------------------------------------------------------- 1 | #define foo() bar 2 | 3 | foo()baz 4 | 5 | #define BAD(x) x 6 | +BAD(1) 7 | +BAD(=) 8 | +BAD(+) 9 | >BAD(>) 10 | >>BAD(=) 11 | >BAD(>=) 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/pp/pp-gen-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-gen-1.c" 2 | 3 | 4 | bar baz 5 | 6 | 7 | +1 8 | + = 9 | + + 10 | > > 11 | >> = 12 | > >= 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/pp/pp-gen-1.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-gen-1.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-if-1.c: -------------------------------------------------------------------------------- 1 | #ifdef 2 | no1 3 | #endif 4 | #ifdef 2 5 | no2 6 | #endif 7 | #ifdef a b 8 | no3 9 | #endif 10 | #else 11 | #endif -------------------------------------------------------------------------------- /tests/pp/pp-if-1.c.i: -------------------------------------------------------------------------------- 1 | # 3 "pp-if-1.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/pp/pp-if-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-if-1.c(1)[7]..(2)[1]: error: Identifier expected after #ifdef 2 | pp-if-1.c(4)[8..9]: error: Identifier expected after #ifdef 3 | pp-if-1.c(7)[10..11]: error: Extra tokens after end of #ifdef 4 | pp-if-1.c(10)[2..6]: error: #else without #if 5 | pp-if-1.c(11)[2..7]: error: #endif without #if 6 | -------------------------------------------------------------------------------- /tests/pp/pp-if-2.c: -------------------------------------------------------------------------------- 1 | #define Y1 2 | 3 | #ifdef N1 4 | no1 5 | "unterm 6 | #ifdef Y1 7 | no2 8 | #else 9 | no3 10 | #endif 11 | #else 12 | yes1 13 | #ifndef N1 14 | yes2 15 | #else 16 | no4 17 | #endif 18 | #endif 19 | end -------------------------------------------------------------------------------- /tests/pp/pp-if-2.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-if-2.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | yes1 14 | 15 | yes2 16 | 17 | 18 | 19 | 20 | end -------------------------------------------------------------------------------- /tests/pp/pp-if-2.c.msg: -------------------------------------------------------------------------------- 1 | pp-if-2.c(5)[1..8]: warning: Unterminated string constant 2 | -------------------------------------------------------------------------------- /tests/pp/pp-if-3.c: -------------------------------------------------------------------------------- 1 | #ifndef XX 2 | a 3 | b 4 | c -------------------------------------------------------------------------------- /tests/pp/pp-if-3.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-if-3.c" 2 | 3 | a 4 | b 5 | c -------------------------------------------------------------------------------- /tests/pp/pp-if-3.c.msg: -------------------------------------------------------------------------------- 1 | pp-if-3.c(1)[2..8]: error: Unterminated #ifndef 2 | -------------------------------------------------------------------------------- /tests/pp/pp-if-4.c: -------------------------------------------------------------------------------- 1 | #if -1 < 1 2 | yes1; 3 | #else 4 | no1; 5 | #endif 6 | 7 | #if -1 < 1llu 8 | no2; 9 | #else 10 | yes2; 11 | #endif 12 | 13 | #if !defined BLA 14 | yes3; 15 | #else 16 | no3; 17 | #endif 18 | 19 | #if !!defined BLA 20 | no4; 21 | #else 22 | yes4; 23 | #endif 24 | 25 | #if !defined( BLA ) 26 | yes5; 27 | #else 28 | no5; 29 | #endif 30 | 31 | #if BLA 32 | no6; 33 | #else 34 | yes6; 35 | #endif 36 | 37 | #if !BLA 38 | yes7; 39 | #else 40 | no7; 41 | #endif 42 | 43 | #define MY 1 44 | #if MY 45 | yes8; 46 | #else 47 | no8; 48 | #endif 49 | 50 | #if defined(MY) 51 | yes9; 52 | #else 53 | no9; 54 | #endif 55 | 56 | #if defined MY 57 | yes10; 58 | #else 59 | no10; 60 | #endif 61 | 62 | #if defined(MY) && MY 63 | yes11; 64 | #else 65 | no11; 66 | #endif 67 | -------------------------------------------------------------------------------- /tests/pp/pp-if-4.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-if-4.c" 2 | 3 | yes1; 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | yes2; 12 | 13 | 14 | 15 | yes3; 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | yes4; 24 | 25 | 26 | 27 | yes5; 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | yes6; 36 | 37 | 38 | 39 | yes7; 40 | 41 | 42 | 43 | 44 | 45 | 46 | yes8; 47 | 48 | 49 | 50 | 51 | 52 | yes9; 53 | 54 | 55 | 56 | 57 | 58 | yes10; 59 | 60 | 61 | 62 | 63 | 64 | yes11; 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /tests/pp/pp-if-4.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-if-4.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-if-5.c: -------------------------------------------------------------------------------- 1 | #if defined 2 | #endif 3 | 4 | #if defined 1 5 | #endif 6 | 7 | #if defined( x 1 8 | #endif 9 | -------------------------------------------------------------------------------- /tests/pp/pp-if-5.c.i: -------------------------------------------------------------------------------- 1 | # 2 "pp-if-5.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /tests/pp/pp-if-5.c.msg: -------------------------------------------------------------------------------- 1 | pp-if-5.c(1)[12]..(2)[1]: error: Identifier expected after 'defined' 2 | pp-if-5.c(4)[13..14]: error: Identifier expected after 'defined' 3 | pp-if-5.c(7)[16..17]: error: Missing closing ')' after defined 4 | -------------------------------------------------------------------------------- /tests/pp/pp-inc-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include aa 3 | #include "df-df 4 | #include "df-df" 5 | #include < a 1 2 .h 6 | #include < a 1 2 .h > 7 | 8 | #define FF "-missing-file.h-" 9 | #include FF 10 | 11 | #define FF2 <-missing - file2.h- > 12 | #include FF2 13 | 14 | #define FF3 <-missing-file3.h-> 15 | #include FF3 16 | -------------------------------------------------------------------------------- /tests/pp/pp-inc-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-inc-1.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/pp/pp-inc-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-inc-1.c(1)[9]..(2)[1]: error: Invalid #include filename 2 | pp-inc-1.c(2)[10..12]: error: Invalid #include filename 3 | pp-inc-1.c(3)[10..16]: error: Unterminated string constant 4 | pp-inc-1.c(3)[2..9]: error: Can't find include file 'df-df' 5 | pp-inc-1.c(4)[2..9]: error: Can't find include file 'df-df' 6 | pp-inc-1.c(5)[25]..(6)[1]: error: Missing #include terminating > character 7 | pp-inc-1.c(5)[2..9]: error: Can't find include file ' a 1 2 .h' 8 | pp-inc-1.c(6)[2..9]: error: Can't find include file ' a 1 2 .h ' 9 | pp-inc-1.c(9)[2..9]: error: Can't find include file '-missing-file.h-' 10 | pp-inc-1.c(12)[2..9]: error: Can't find include file '-missing - file2.h- ' 11 | pp-inc-1.c(15)[2..9]: error: Can't find include file '-missing-file3.h-' 12 | -------------------------------------------------------------------------------- /tests/pp/pp-line-1.c: -------------------------------------------------------------------------------- 1 | #line 2 | #line a 3 | #line -1 4 | #line 3.3 5 | #line 99999999999999999999 6 | #line 0x20 7 | #line 100 "\xN" 8 | #line 100 blaa -------------------------------------------------------------------------------- /tests/pp/pp-line-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-line-1.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | # 100 "\000N" 9 | -------------------------------------------------------------------------------- /tests/pp/pp-line-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-line-1.c(1)[6]..(2)[1]: error: Integer line number expected after #line 2 | pp-line-1.c(2)[7..8]: error: Integer line number expected after #line 3 | pp-line-1.c(3)[7..8]: error: Integer line number expected after #line 4 | pp-line-1.c(4)[7..10]: error: Integer line number expected after #line 5 | pp-line-1.c(5)[7..27]: error: Constant is too large 6 | pp-line-1.c(5)[7..27]: error: Line number outside of allowed range after #line 7 | pp-line-1.c(6)[7..11]: error: Only decimal integers supported after #line 8 | pp-line-1.c(7)[12..15]: error: Invalid hex escape sequence in string constant 9 | N(100)[11..15]: error: Filename must be a string constant after #line 10 | -------------------------------------------------------------------------------- /tests/pp/pp-line-2.c: -------------------------------------------------------------------------------- 1 | 1; 2 | #line 20 3 | 2; -------------------------------------------------------------------------------- /tests/pp/pp-line-2.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-line-2.c" 2 | 1; 3 | # 20 "pp-line-2.c" 4 | 2; -------------------------------------------------------------------------------- /tests/pp/pp-line-2.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-line-2.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-line-3.c: -------------------------------------------------------------------------------- 1 | #line 100 2 | #line 3008 3 | #line 505 "file.txt" 4 | 5 | #define N(f) 1000 #f 6 | #line N(file_c) 7 | 8 | 1; -------------------------------------------------------------------------------- /tests/pp/pp-line-3.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-line-3.c" 2 | # 100 "pp-line-3.c" 3 | # 3008 "pp-line-3.c" 4 | # 505 "file.txt" 5 | 6 | 7 | # 1000 "file_c" 8 | 9 | 1; -------------------------------------------------------------------------------- /tests/pp/pp-line-3.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-line-3.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-mark-1.c: -------------------------------------------------------------------------------- 1 | # 2 | # a 3 | # -1 4 | # 3.3 5 | # 99999999999999999999 6 | # 0x20 7 | # 100 "\xN" 8 | # 100 blaa 9 | # 100 "file" ab 10 | # 100 "file2" 1 -------------------------------------------------------------------------------- /tests/pp/pp-mark-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-mark-1.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | # 100 "\000N" 9 | 10 | # 100 "file" 11 | -------------------------------------------------------------------------------- /tests/pp/pp-mark-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-mark-1.c(2)[3..4]: error: Invalid preprocessor directive #a 2 | pp-mark-1.c(3)[3..4]: error: Invalid preprocessor directive #- 3 | pp-mark-1.c(4)[3..6]: error: Invalid preprocessor directive #3.3 4 | pp-mark-1.c(5)[3..23]: error: Constant is too large 5 | pp-mark-1.c(5)[3..23]: error: Line number outside of allowed range after # 6 | pp-mark-1.c(6)[3..7]: error: Only decimal integers supported after # 7 | pp-mark-1.c(7)[8..11]: error: Invalid hex escape sequence in string constant 8 | N(100)[7..11]: error: Missing filename after # 9 | N(101)[14..16]: error: Invalid flag 'ab' after # 10 | file(100)[15..16]: warning: Ignoring unsupported GCC-style marker flags 11 | -------------------------------------------------------------------------------- /tests/pp/pp-mark-2.c: -------------------------------------------------------------------------------- 1 | 1; 2 | #line 20 3 | 2; -------------------------------------------------------------------------------- /tests/pp/pp-mark-2.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-mark-2.c" 2 | 1; 3 | # 20 "pp-mark-2.c" 4 | 2; -------------------------------------------------------------------------------- /tests/pp/pp-mark-2.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-mark-2.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-mark-3.c: -------------------------------------------------------------------------------- 1 | #line 100 2 | #line 3008 3 | #line 505 "file.txt" 4 | 5 | #define N(f) 1000 #f 6 | #line N(file_c) 7 | 8 | 1; -------------------------------------------------------------------------------- /tests/pp/pp-mark-3.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-mark-3.c" 2 | # 100 "pp-mark-3.c" 3 | # 3008 "pp-mark-3.c" 4 | # 505 "file.txt" 5 | 6 | 7 | # 1000 "file_c" 8 | 9 | 1; -------------------------------------------------------------------------------- /tests/pp/pp-mark-3.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-mark-3.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-t1.c: -------------------------------------------------------------------------------- 1 | a b c 2 | 1 2 3 | 4 | abc\ 5 | de\ 6 | f 1 2 3 7 | 8 | 3 + 2; 9 | -------------------------------------------------------------------------------- /tests/pp/pp-t1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-t1.c" 2 | a b c 3 | 1 2 4 | 5 | abcdef 6 | 7 | 1 2 3 8 | 9 | 3 + 2; 10 | -------------------------------------------------------------------------------- /tests/pp/pp-t1.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-t1.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-t2.c: -------------------------------------------------------------------------------- 1 | abc\ 2 | d\ 3 | e 1 2 4 | -------------------------------------------------------------------------------- /tests/pp/pp-t2.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-t2.c" 2 | abcde 3 | 4 | 1 2 5 | -------------------------------------------------------------------------------- /tests/pp/pp-t2.c.msg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmikov/c99/10fe901c554d8976fa5fb817effb0b201aa251f7/tests/pp/pp-t2.c.msg -------------------------------------------------------------------------------- /tests/pp/pp-undef-1.c: -------------------------------------------------------------------------------- 1 | #undef 2 | #undef 1 3 | #undef xxx 4 | #undef xxx 1 5 | 6 | #define MM 1 7 | MM 8 | #undef MM 9 | MM 10 | #undef MM 11 | 12 | __LINE__; 13 | #undef __LINE__ 14 | __LINE__; 15 | -------------------------------------------------------------------------------- /tests/pp/pp-undef-1.c.i: -------------------------------------------------------------------------------- 1 | # 1 "pp-undef-1.c" 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 9 | 10 | MM 11 | 12 | 13 | 12; 14 | 15 | __LINE__; 16 | -------------------------------------------------------------------------------- /tests/pp/pp-undef-1.c.msg: -------------------------------------------------------------------------------- 1 | pp-undef-1.c(1)[7]..(2)[1]: error: An identifier macro name expected after #undef 2 | pp-undef-1.c(2)[8..9]: error: An identifier macro name expected after #undef 3 | pp-undef-1.c(4)[12..13]: error: Extra tokens after end of #undef 4 | pp-undef-1.c(13)[8..16]: warning: undefining '__LINE__' 5 | -------------------------------------------------------------------------------- /tests/pp/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | app=../../cpp.sh 4 | 5 | for tst in *.c; do 6 | echo "Testing $tst" 7 | $app $tst 2>$tst.msg.run >$tst.i.run 8 | if diff -q -a $tst.i $tst.i.run > /dev/null; then 9 | rm $tst.i.run 10 | else 11 | diff -y -a $tst.i $tst.i.run | less -S 12 | fi 13 | if diff -q -a $tst.msg $tst.msg.run > /dev/null; then 14 | rm $tst.msg.run 15 | else 16 | diff -y -a $tst.msg $tst.msg.run | less -S 17 | fi 18 | done --------------------------------------------------------------------------------