diff --git a/src/main/java/org/anarres/cpp/LexerSource.java b/src/main/java/org/anarres/cpp/LexerSource.java index 0b381b9..98e146b 100644 --- a/src/main/java/org/anarres/cpp/LexerSource.java +++ b/src/main/java/org/anarres/cpp/LexerSource.java @@ -510,11 +510,14 @@ private Token _number_suffix(StringBuilder text, NumericValue value, int d) d = read(); } // This should probably be isPunct() || isWhite(). else if (Character.isLetter(d) || d == '_') { + // We've encountered something initially identified as a number. + // Read in the rest of this token as an identifer but return it as an invalid. + while(Character.isLetterOrDigit(d) || d == '_') { + text.append((char)d); + d = read(); + } unread(d); - value.setFlags(flags); - return invalid(text, - "Invalid suffix \"" + (char) d - + "\" on numeric constant"); + return new Token(INVALID,text.toString()); } else { unread(d); value.setFlags(flags); diff --git a/src/main/java/org/anarres/cpp/Preprocessor.java b/src/main/java/org/anarres/cpp/Preprocessor.java index 0ad1538..180684f 100644 --- a/src/main/java/org/anarres/cpp/Preprocessor.java +++ b/src/main/java/org/anarres/cpp/Preprocessor.java @@ -119,6 +119,9 @@ public String getName() { private VirtualFileSystem filesystem; private PreprocessorListener listener; + HashSet<String> quotedImports=new HashSet<String>(); + HashSet<String> sysImports=new HashSet<String>(); + public Preprocessor() { this.inputs = new ArrayList<Source>(); @@ -737,6 +740,7 @@ private boolean macro(Macro m, Token orig) case WHITESPACE: case CCOMMENT: case CPPCOMMENT: + case NL: /* Avoid duplicating spaces. */ space = true; break; @@ -1127,6 +1131,25 @@ private void include( } if (include(quoteincludepath, name)) return; + } else { + int forwardSlashPos=name.indexOf('/'); + if (forwardSlashPos!=-1) { + String frameworkName=name.substring(0,forwardSlashPos); + String includeName=name.substring(forwardSlashPos+1); + for (String frameworkPath:frameworkspath) { + File frameworkFile=new File(frameworkPath,frameworkName+".framework"); + if (!frameworkFile.exists() || !frameworkFile.isDirectory()) + continue; + File frameworkHeadersFile=new File(frameworkFile,"Headers"); + if (!frameworkHeadersFile.exists() || !frameworkHeadersFile.isDirectory()) + continue; + File includeFile=new File(frameworkHeadersFile,includeName); + if (!includeFile.exists() || !includeFile.isFile()) + continue; + if (include(filesystem.getFile(includeFile.getCanonicalPath()))) + return; + } + } } if (include(sysincludepath, name)) @@ -1146,7 +1169,7 @@ private void include( } @Nonnull - private Token include(boolean next) + private Token include(boolean next,boolean isImport) throws IOException, LexerException { LexerSource lexer = (LexerSource) source; @@ -1196,13 +1219,20 @@ private Token include(boolean next) } } - /* Do the inclusion. */ - include(source.getPath(), tok.getLine(), name, quoted, next); + HashSet<String> importMap=quoted?quotedImports:sysImports; + if (!isImport || !importMap.contains(name)) { + /* Do the inclusion. */ + include(source.getPath(), tok.getLine(), name, quoted, next); + + importMap.add(name); - /* 'tok' is the 'nl' after the include. We use it after the - * #line directive. */ - if (getFeature(Feature.LINEMARKERS)) - return line_token(1, source.getName(), " 1"); + /* 'tok' is the 'nl' after the include. We use it after the + * #line directive. */ + if (getFeature(Feature.LINEMARKERS)) + return line_token(1, source.getName(), " 1"); + } else { + warning(tok,"Already imported:"+name); + } return tok; } finally { lexer.setInclude(false); @@ -1494,7 +1524,7 @@ private long expr(int priority) tok = expr_token(); if (tok.getType() != ')') { expr_untoken(tok); - error(tok, "missing ) in expression"); + error(tok, "missing ) in expression at "+tok); return 0; } break; @@ -1609,7 +1639,17 @@ private long expr(int priority) break; case '?': - /* XXX Handle this? */ + { + tok = expr_token(); + if (tok.getType() != ':') { + expr_untoken(tok); + error(tok, "missing : in conditional expression"); + return 0; + } + long falseResult=expr(0); + lhs = (lhs!=0) ? rhs : falseResult; + } + break; default: error(op, @@ -1781,6 +1821,7 @@ private Token _token() case RSH: case RSH_EQ: case STRING: + case SQSTRING : case XOR_EQ: return tok; @@ -1851,11 +1892,12 @@ private Token _token() return undef(); // break; + case PP_IMPORT : case PP_INCLUDE: if (!isActive()) return source_skipline(false); else - return include(false); + return include(false,ppcmd==PP_IMPORT); // break; case PP_INCLUDE_NEXT: if (!isActive()) @@ -1866,7 +1908,7 @@ private Token _token() ); return source_skipline(false); } - return include(true); + return include(true,false); // break; case PP_WARNING: