00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "cppPreprocessor.h"
00021 #include "cppExpressionParser.h"
00022 #include "cppExpression.h"
00023 #include "cppScope.h"
00024 #include "cppIdentifier.h"
00025 #include "cppTemplateScope.h"
00026 #include "cppTemplateParameterList.h"
00027 #include "cppSimpleType.h"
00028 #include "cppGlobals.h"
00029 #include "cppCommentBlock.h"
00030 #include "cppBison.h"
00031 #include "indent.h"
00032
00033 #include <assert.h>
00034 #include <ctype.h>
00035
00036
00037
00038
00039
00040
00041 static CPPVisibility preprocessor_vis = V_public;
00042
00043 static int
00044 hex_val(int c) {
00045 switch (c) {
00046 case '0':
00047 case '1':
00048 case '2':
00049 case '3':
00050 case '4':
00051 case '5':
00052 case '6':
00053 case '7':
00054 case '8':
00055 case '9':
00056 return (c - '0');
00057
00058 default:
00059 return (tolower(c) - 'a' + 10);
00060 }
00061 }
00062
00063 static string
00064 trim_blanks(const string &str) {
00065 size_t first, last;
00066
00067 if(str.empty())
00068 return str;
00069
00070 first = 0;
00071 while (first < str.length() && isspace(str[first])) {
00072 first++;
00073 }
00074
00075 last = str.length() - 1;
00076 while (last > first && isspace(str[last])) {
00077 last--;
00078 }
00079
00080 return str.substr(first, last - first + 1);
00081 }
00082
00083
00084
00085
00086
00087
00088 CPPPreprocessor::InputFile::
00089 InputFile() {
00090 _in = NULL;
00091 _ignore_manifest = NULL;
00092 _line_number = 1;
00093 _col_number = 1;
00094 _lock_position = false;
00095 }
00096
00097
00098
00099
00100
00101
00102 CPPPreprocessor::InputFile::
00103 ~InputFile() {
00104 if (_in != NULL) {
00105 delete _in;
00106 }
00107 }
00108
00109
00110
00111
00112
00113
00114 bool CPPPreprocessor::InputFile::
00115 open(const CPPFile &file) {
00116 assert(_in == NULL);
00117
00118 _file = file;
00119 ifstream *in = new ifstream;
00120 _in = in;
00121
00122 return _file._filename.open_read(*in);
00123 }
00124
00125
00126
00127
00128
00129
00130 bool CPPPreprocessor::InputFile::
00131 connect_input(const string &input) {
00132 assert(_in == NULL);
00133
00134 _input = input;
00135 _in = new istringstream(_input);
00136 return !_in->fail();
00137 }
00138
00139
00140
00141
00142
00143
00144 int CPPPreprocessor::InputFile::
00145 get() {
00146 assert(_in != NULL);
00147 int c = _in->get();
00148
00149
00150
00151
00152 while (c == '\r') {
00153 c = _in->get();
00154 }
00155
00156 switch (c) {
00157 case EOF:
00158 break;
00159
00160 case '\n':
00161 if (!_lock_position) {
00162 _line_number++;
00163 _col_number = 1;
00164 }
00165 break;
00166
00167 default:
00168 if (!_lock_position) {
00169 _col_number++;
00170 }
00171 }
00172
00173 return c;
00174 }
00175
00176
00177
00178
00179
00180
00181 CPPPreprocessor::
00182 CPPPreprocessor() {
00183 _state = S_eof;
00184 _paren_nesting = 0;
00185 _angle_bracket_found = false;
00186 _unget = '\0';
00187 _last_c = '\0';
00188 _start_of_line = true;
00189 _last_cpp_comment = false;
00190 _save_comments = true;
00191
00192 _resolve_identifiers = true;
00193
00194 _warning_count = 0;
00195 _error_count = 0;
00196 #ifdef CPP_VERBOSE_LEX
00197 _token_index = 0;
00198 #endif
00199 _verbose = 1;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 void CPPPreprocessor::
00210 set_verbose(int verbose) {
00211 _verbose = verbose;
00212 }
00213
00214
00215
00216
00217
00218
00219 int CPPPreprocessor::
00220 get_verbose() const {
00221 return _verbose;
00222 }
00223
00224
00225
00226
00227
00228
00229 void CPPPreprocessor::
00230 copy_filepos(const CPPPreprocessor &other) {
00231 assert(!_files.empty());
00232 _files.back()._file = other.get_file();
00233 _files.back()._line_number = other.get_line_number();
00234 _files.back()._col_number = other.get_col_number();
00235 }
00236
00237
00238
00239
00240
00241
00242 CPPFile CPPPreprocessor::
00243 get_file() const {
00244 if (_files.empty()) {
00245 return CPPFile("");
00246 }
00247 return _files.back()._file;
00248 }
00249
00250
00251
00252
00253
00254
00255 int CPPPreprocessor::
00256 get_line_number() const {
00257 if (_files.empty()) {
00258 return 0;
00259 }
00260 return _files.back()._line_number;
00261 }
00262
00263
00264
00265
00266
00267
00268 int CPPPreprocessor::
00269 get_col_number() const {
00270 if (_files.empty()) {
00271 return 0;
00272 }
00273 return _files.back()._col_number;
00274 }
00275
00276
00277
00278
00279
00280
00281 CPPToken CPPPreprocessor::
00282 get_next_token() {
00283
00284 #ifdef CPP_VERBOSE_LEX
00285 CPPToken tok = get_next_token0();
00286 indent(cerr, _files.size() * 2)
00287 << _token_index++ << ". " << tok << "\n";
00288 return tok;
00289 }
00290
00291 CPPToken CPPPreprocessor::
00292 get_next_token0() {
00293 #endif
00294
00295
00296
00297
00298
00299 CPPToken token(0);
00300 if (!_saved_tokens.empty()) {
00301 token = _saved_tokens.back();
00302 _saved_tokens.pop_back();
00303 } else {
00304 token = internal_get_next_token();
00305 }
00306
00307 int first_line = token._lloc.first_line;
00308 int first_col = token._lloc.first_column;
00309 CPPFile first_file = token._lloc.file;
00310
00311 if (token._token == '#') {
00312
00313 token = internal_get_next_token();
00314 if (token._token == SIMPLE_IDENTIFIER || token._token == STRING) {
00315 token._token = STRING;
00316 } else {
00317
00318
00319 _saved_tokens.push_back(token);
00320 token._token = STRING;
00321 token._lval.str = "";
00322 }
00323 }
00324
00325 if (_resolve_identifiers &&
00326 (token._token == SIMPLE_IDENTIFIER || token._token == SCOPE)) {
00327
00328
00329
00330
00331 string name;
00332
00333
00334
00335
00336
00337 if (token._token == SIMPLE_IDENTIFIER) {
00338 name = token._lval.str;
00339 token = internal_get_next_token();
00340 }
00341
00342 CPPIdentifier *ident = new CPPIdentifier(name, token._lloc.file);
00343 YYSTYPE result;
00344 result.u.identifier = ident;
00345
00346 if (token._token == '<') {
00347
00348
00349
00350
00351 CPPDeclaration *decl = ident->find_template(current_scope, global_scope);
00352 if (decl != NULL) {
00353 ident->_names.back().set_templ
00354 (nested_parse_template_instantiation(decl->get_template_scope()));
00355 token = internal_get_next_token();
00356 }
00357 }
00358
00359 while (token._token == SCOPE || token._token == TOKENPASTE) {
00360 if (token._token == TOKENPASTE) {
00361
00362
00363 token = internal_get_next_token();
00364 if (token._token == SIMPLE_IDENTIFIER) {
00365 name += token._lval.str;
00366 ident->_names.back().append_name(token._lval.str);
00367
00368 token = internal_get_next_token();
00369
00370 } else {
00371
00372 }
00373
00374 } else {
00375 name += "::";
00376 token = internal_get_next_token();
00377 string token_prefix;
00378
00379 if (token._token == '~') {
00380
00381
00382
00383 name += "~";
00384 token_prefix = "~";
00385 token = internal_get_next_token();
00386 }
00387
00388 if (token._token != SIMPLE_IDENTIFIER) {
00389
00390
00391
00392 if (token._token == KW_OPERATOR) {
00393
00394
00395
00396 token._lval = result;
00397 return token;
00398 }
00399 _saved_tokens.push_back(token);
00400 return CPPToken(SCOPING, first_line, first_col, first_file,
00401 name, result);
00402 }
00403
00404 name += token._lval.str;
00405 ident->_names.push_back(token_prefix + token._lval.str);
00406
00407 token = internal_get_next_token();
00408 }
00409
00410 if (token._token == '<') {
00411
00412
00413
00414
00415 CPPDeclaration *decl =
00416 ident->find_template(current_scope, global_scope);
00417 if (decl != NULL) {
00418 ident->_names.back().set_templ
00419 (nested_parse_template_instantiation(decl->get_template_scope()));
00420 token = internal_get_next_token();
00421 }
00422 }
00423 }
00424
00425
00426 _saved_tokens.push_back(token);
00427
00428 int token_type = IDENTIFIER;
00429 CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope);
00430 if (decl != NULL &&
00431 (decl->as_typedef() != NULL || decl->as_type() != NULL)) {
00432 token_type = TYPENAME_IDENTIFIER;
00433 }
00434
00435 return CPPToken(token_type, first_line, first_col, first_file,
00436 name, result);
00437 }
00438
00439
00440 return token;
00441 }
00442
00443
00444
00445
00446
00447
00448 void CPPPreprocessor::
00449 warning(const string &message, int line, int col, CPPFile file) {
00450 if (_verbose >= 2) {
00451 if (line == 0) {
00452 line = get_line_number();
00453 col = get_col_number();
00454 }
00455 if (file.empty()) {
00456 file = get_file();
00457 }
00458 indent(cerr, _files.size() * 2)
00459 << "*** Warning in " << file
00460 << " near line " << line << ", column " << col << ":\n";
00461 indent(cerr, _files.size() * 2)
00462 << message << "\n";
00463 }
00464 _warning_count++;
00465 }
00466
00467
00468
00469
00470
00471
00472 void CPPPreprocessor::
00473 error(const string &message, int line, int col, CPPFile file) {
00474 if (_state == S_nested || _state == S_end_nested) {
00475
00476
00477 return;
00478 };
00479
00480 if (_verbose >= 1) {
00481 if (line == 0) {
00482 line = get_line_number();
00483 col = get_col_number();
00484 }
00485 if (file.empty()) {
00486 file = get_file();
00487 }
00488 indent(cerr, _files.size() * 2)
00489 << "*** Error in " << file
00490 << " near line " << line << ", column " << col << ":\n";
00491 indent(cerr, _files.size() * 2)
00492 << message << "\n";
00493 }
00494 _error_count++;
00495 }
00496
00497
00498
00499
00500
00501
00502 int CPPPreprocessor::
00503 get_warning_count() const {
00504 return _warning_count;
00505 }
00506
00507
00508
00509
00510
00511
00512 int CPPPreprocessor::
00513 get_error_count() const {
00514 return _error_count;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524 CPPCommentBlock *CPPPreprocessor::
00525 get_comment_before(int line, CPPFile file) {
00526 CPPComments::reverse_iterator ci;
00527 ci = _comments.rbegin();
00528
00529 int wrong_file_count = 0;
00530 while (ci != _comments.rend()) {
00531 CPPCommentBlock *comment = (*ci);
00532 if (comment->_file == file) {
00533 wrong_file_count = 0;
00534 if (comment->_last_line == line || comment->_last_line == line - 1) {
00535 return comment;
00536 }
00537
00538 if (comment->_last_line < line) {
00539 return (CPPCommentBlock *)NULL;
00540 }
00541 } else {
00542 wrong_file_count++;
00543 if (wrong_file_count > 10) {
00544 return (CPPCommentBlock *)NULL;
00545 }
00546 }
00547
00548 ++ci;
00549 }
00550
00551 return (CPPCommentBlock *)NULL;
00552 }
00553
00554
00555
00556
00557
00558
00559 bool CPPPreprocessor::
00560 init_cpp(const CPPFile &file) {
00561 _state = S_normal;
00562 _saved_tokens.push_back(CPPToken(START_CPP));
00563 _last_c = '\0';
00564
00565 return push_file(file);
00566 }
00567
00568
00569
00570
00571
00572
00573 bool CPPPreprocessor::
00574 init_const_expr(const string &expr) {
00575 _state = S_normal;
00576 _saved_tokens.push_back(CPPToken(START_CONST_EXPR));
00577
00578 return push_string(expr, false);
00579 }
00580
00581
00582
00583
00584
00585
00586 bool CPPPreprocessor::
00587 init_type(const string &type) {
00588 _state = S_normal;
00589 _saved_tokens.push_back(CPPToken(START_TYPE));
00590
00591 return push_string(type, false);
00592 }
00593
00594
00595
00596
00597
00598
00599 bool CPPPreprocessor::
00600 push_file(const CPPFile &file) {
00601 if (_verbose >= 2) {
00602 indent(cerr, _files.size() * 2)
00603 << "Reading " << file << "\n";
00604 }
00605 _files.push_back(InputFile());
00606 InputFile &infile = _files.back();
00607
00608 if (infile.open(file)) {
00609
00610
00611 _parsed_files.insert(file);
00612
00613 infile._prev_last_c = _last_c;
00614 _last_c = '\0';
00615 _start_of_line = true;
00616 return true;
00617 }
00618
00619 _files.pop_back();
00620 return false;
00621 }
00622
00623
00624
00625
00626
00627
00628 bool CPPPreprocessor::
00629 push_string(const string &input, bool lock_position) {
00630 #ifdef CPP_VERBOSE_LEX
00631 indent(cerr, _files.size() * 2)
00632 << "Pushing to string \"" << input
00633 << "\"\nlock_position = " << lock_position << "\n";
00634 #endif
00635 CPPFile first_file = get_file();
00636 int first_line = get_line_number();
00637 int first_col = get_col_number();
00638
00639 _files.push_back(InputFile());
00640 InputFile &infile = _files.back();
00641
00642 if (infile.connect_input(input)) {
00643 if (lock_position) {
00644 infile._file = first_file;
00645 infile._line_number = first_line;
00646 infile._col_number = first_col;
00647 infile._lock_position = true;
00648 }
00649
00650 infile._prev_last_c = _last_c;
00651 _last_c = '\0';
00652 return true;
00653 }
00654
00655 #ifdef CPP_VERBOSE_LEX
00656 indent(cerr, _files.size() * 2)
00657 << "Unable to read string\n";
00658 #endif
00659
00660 _files.pop_back();
00661 return false;
00662 }
00663
00664
00665
00666
00667
00668
00669
00670 string CPPPreprocessor::
00671 expand_manifests(const string &input_expr) {
00672
00673 string expr = input_expr;
00674
00675
00676
00677
00678
00679
00680 set<const CPPManifest *> already_expanded;
00681
00682 bool manifest_found;
00683 do {
00684 manifest_found = false;
00685 size_t p = 0;
00686 while (p < expr.size()) {
00687 if (isalpha(expr[p]) || expr[p] == '_') {
00688 size_t q = p;
00689 while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) {
00690 p++;
00691 }
00692 string ident = expr.substr(q, p - q);
00693
00694
00695 if (ident == "defined") {
00696 expand_defined_function(expr, q, p);
00697 } else {
00698
00699 Manifests::const_iterator mi = _manifests.find(ident);
00700 if (mi != _manifests.end()) {
00701 const CPPManifest *manifest = (*mi).second;
00702 if (already_expanded.insert(manifest).second) {
00703 expand_manifest_inline(expr, q, p, (*mi).second);
00704 manifest_found = true;
00705 }
00706 }
00707 }
00708 } else {
00709 p++;
00710 }
00711 }
00712
00713
00714
00715
00716 } while (manifest_found);
00717
00718 return expr;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 CPPExpression *CPPPreprocessor::
00733 parse_expr(const string &input_expr, CPPScope *current_scope,
00734 CPPScope *global_scope) {
00735 string expr = expand_manifests(input_expr);
00736
00737 CPPExpressionParser ep(current_scope, global_scope);
00738 ep._verbose = 0;
00739 if (ep.parse_expr(expr, *this)) {
00740 return ep._expr;
00741 } else {
00742 return (CPPExpression *)NULL;
00743 }
00744 }
00745
00746
00747
00748
00749
00750
00751 CPPToken CPPPreprocessor::
00752 internal_get_next_token() {
00753 if (_state == S_eof || _state == S_end_nested) {
00754 return CPPToken::eof();
00755 }
00756
00757 int c = _last_c;
00758 _last_c = '\0';
00759 if (c == '\0' || c == EOF) {
00760 c = get();
00761 }
00762
00763
00764
00765 c = skip_whitespace(c);
00766 while (c == '#' && _start_of_line && !should_ignore_preprocessor()) {
00767 c = skip_whitespace(process_directive(c));
00768 }
00769
00770 if (c == '\'') {
00771 return get_quoted_char(c);
00772 } else if (c == '"') {
00773 return get_quoted_string(c);
00774 } else if (isalpha(c) || c == '_') {
00775 return get_identifier(c);
00776 } else if (isdigit(c)) {
00777 return get_number(c);
00778 }
00779
00780 _last_c = c;
00781 if (c == EOF) {
00782 _state = S_eof;
00783 return CPPToken::eof();
00784 }
00785
00786 CPPFile first_file = get_file();
00787 int first_line = get_line_number();
00788 int first_col = get_col_number();
00789
00790
00791 int next_c = get();
00792 if (c == '.' && isdigit(next_c)) {
00793 return get_number(c, next_c);
00794 }
00795
00796
00797 _last_c = get();
00798
00799 switch (c) {
00800 case '+':
00801 if (next_c == '+') return CPPToken(PLUSPLUS, first_line, first_col, first_file);
00802 if (next_c == '=') return CPPToken(PLUSEQUAL, first_line, first_col, first_file);
00803 break;
00804
00805 case '-':
00806 if (next_c == '-') return CPPToken(MINUSMINUS, first_line, first_col, first_file);
00807 if (next_c == '=') return CPPToken(MINUSEQUAL, first_line, first_col, first_file);
00808 if (next_c == '>' && _last_c == '*') {
00809 _last_c = get();
00810 return CPPToken(POINTSAT_STAR, first_line, first_col, first_file);
00811 }
00812 if (next_c == '>') return CPPToken(POINTSAT, first_line, first_col, first_file);
00813 break;
00814
00815 case '<':
00816 if (next_c == '<' && _last_c == '=') {
00817 _last_c = get();
00818 return CPPToken(LSHIFTEQUAL, first_line, first_col, first_file);
00819 }
00820 if (next_c == '<') return CPPToken(LSHIFT, first_line, first_col, first_file);
00821 if (next_c == '=') return CPPToken(LECOMPARE, first_line, first_col, first_file);
00822 break;
00823
00824 case '>':
00825 if (next_c == '>' && _last_c == '=') {
00826 _last_c = get();
00827 return CPPToken(RSHIFTEQUAL, first_line, first_col, first_file);
00828 }
00829 if (next_c == '>') return CPPToken(RSHIFT, first_line, first_col, first_file);
00830 if (next_c == '=') return CPPToken(GECOMPARE, first_line, first_col, first_file);
00831 break;
00832
00833 case '|':
00834 if (next_c == '|') return CPPToken(OROR, first_line, first_col, first_file);
00835 if (next_c == '=') return CPPToken(OREQUAL, first_line, first_col, first_file);
00836 break;
00837
00838 case '&':
00839 if (next_c == '&') return CPPToken(ANDAND, first_line, first_col, first_file);
00840 if (next_c == '=') return CPPToken(ANDEQUAL, first_line, first_col, first_file);
00841 break;
00842
00843 case '^':
00844 if (next_c == '=') return CPPToken(XOREQUAL, first_line, first_col, first_file);
00845 break;
00846
00847 case '=':
00848 if (next_c == '=') return CPPToken(EQCOMPARE, first_line, first_col, first_file);
00849 break;
00850
00851 case '!':
00852 if (next_c == '=') return CPPToken(NECOMPARE, first_line, first_col, first_file);
00853 break;
00854
00855 case '.':
00856 if (next_c == '*') return CPPToken(DOT_STAR, first_line, first_col, first_file);
00857 if (next_c == '.' && _last_c == '.') {
00858 _last_c = get();
00859 return CPPToken(ELLIPSIS, first_line, first_col, first_file);
00860 }
00861 break;
00862
00863 case ':':
00864 if (next_c == ':') return CPPToken(SCOPE, first_line, first_col, first_file);
00865 break;
00866
00867 case '*':
00868 if (next_c == '=') return CPPToken(TIMESEQUAL, first_line, first_col, first_file);
00869 break;
00870
00871 case '/':
00872 if (next_c == '=') return CPPToken(DIVIDEEQUAL, first_line, first_col, first_file);
00873 break;
00874
00875 case '%':
00876 if (next_c == '=') return CPPToken(MODEQUAL, first_line, first_col, first_file);
00877 break;
00878
00879
00880
00881 case '#':
00882 if (next_c == '#') return CPPToken(TOKENPASTE, first_line, first_col, first_file);
00883 }
00884
00885
00886
00887 unget(_last_c);
00888 _last_c = next_c;
00889
00890 if (_state == S_nested) {
00891
00892
00893
00894
00895 switch (c) {
00896 case '(':
00897 case '[':
00898 _paren_nesting++;
00899 break;
00900
00901 case ')':
00902 case ']':
00903 _paren_nesting--;
00904 break;
00905
00906 case ',':
00907 if (_paren_nesting <= 0) {
00908 _state = S_end_nested;
00909 return CPPToken::eof();
00910 }
00911 break;
00912
00913 case '>':
00914 if (_paren_nesting <= 0) {
00915 _angle_bracket_found = true;
00916 _state = S_end_nested;
00917 return CPPToken::eof();
00918 }
00919 }
00920 }
00921
00922 return CPPToken(c, first_line, first_col, first_file);
00923 }
00924
00925
00926
00927
00928
00929
00930 int CPPPreprocessor::
00931 skip_whitespace(int c) {
00932 while (c != EOF) {
00933 c = skip_comment(c);
00934
00935 if (c == '\\') {
00936
00937
00938
00939
00940 c = get();
00941 }
00942
00943 if (!isspace(c)) {
00944 return c;
00945 }
00946 c = get();
00947 }
00948 return c;
00949 }
00950
00951
00952
00953
00954
00955
00956 int CPPPreprocessor::
00957 skip_comment(int c) {
00958 if (c == '/') {
00959 int next_c = get();
00960 if (next_c == '*') {
00961 _last_cpp_comment = false;
00962 c = skip_c_comment(get());
00963 } else if (next_c == '/') {
00964 c = skip_cpp_comment(get());
00965 } else {
00966 _last_cpp_comment = false;
00967 unget(next_c);
00968 return c;
00969 }
00970 }
00971 if (!isspace(c)) {
00972 _last_cpp_comment = false;
00973 }
00974 return c;
00975 }
00976
00977
00978
00979
00980
00981
00982 int CPPPreprocessor::
00983 skip_c_comment(int c) {
00984 if (_save_comments) {
00985 CPPCommentBlock *comment = new CPPCommentBlock;
00986 _comments.push_back(comment);
00987
00988 comment->_file = get_file();
00989 comment->_line_number = get_line_number();
00990 comment->_last_line = get_line_number();
00991 comment->_col_number = get_col_number() - 2;
00992 comment->_c_style = true;
00993 comment->_comment = "/*";
00994
00995 while (c != EOF) {
00996 if (c == '*') {
00997 comment->_comment += c;
00998 c = get();
00999 if (c == '/') {
01000 comment->_comment += c;
01001 comment->_last_line = get_line_number();
01002 return get();
01003 }
01004 } else {
01005 comment->_comment += c;
01006 c = get();
01007 }
01008 }
01009
01010 warning("Comment is unterminated",
01011 comment->_line_number, comment->_col_number,
01012 comment->_file);
01013
01014 } else {
01015 CPPFile first_file = get_file();
01016 int first_line_number = get_line_number();
01017 int first_col_number = get_col_number() - 2;
01018
01019 while (c != EOF) {
01020 if (c == '*') {
01021 c = get();
01022 if (c == '/') {
01023 return get();
01024 }
01025 } else {
01026 c = get();
01027 }
01028 }
01029
01030 warning("Comment is unterminated",
01031 first_line_number, first_col_number,
01032 first_file);
01033 }
01034
01035 return c;
01036 }
01037
01038
01039
01040
01041
01042
01043 int CPPPreprocessor::
01044 skip_cpp_comment(int c) {
01045 if (_save_comments) {
01046 CPPCommentBlock *comment;
01047
01048 if (_last_cpp_comment) {
01049
01050
01051
01052 assert(!_comments.empty());
01053 comment = _comments.back();
01054 assert(!comment->_c_style);
01055 comment->_comment += "//";
01056
01057 } else {
01058
01059 comment = new CPPCommentBlock;
01060
01061 comment->_file = get_file();
01062 comment->_line_number = get_line_number();
01063 comment->_last_line = get_line_number();
01064 comment->_col_number = get_col_number() - 2;
01065 comment->_c_style = false;
01066 comment->_comment = "//";
01067
01068 _comments.push_back(comment);
01069 }
01070
01071 while (c != EOF && c != '\n') {
01072 comment->_comment += c;
01073 c = get();
01074 }
01075
01076 comment->_comment += '\n';
01077 comment->_last_line = get_line_number();
01078
01079 _last_cpp_comment = true;
01080
01081 } else {
01082 while (c != EOF && c != '\n') {
01083 c = get();
01084 }
01085 }
01086
01087 return c;
01088 }
01089
01090
01091
01092
01093
01094
01095 int CPPPreprocessor::
01096 process_directive(int c) {
01097 CPPFile first_file = get_file();
01098 int first_line = get_line_number();
01099 int first_col = get_col_number();
01100
01101 string command, args;
01102 c = get_preprocessor_command(c, command);
01103 c = get_preprocessor_args(c, args);
01104
01105 #ifdef CPP_VERBOSE_LEX
01106 indent(cerr, _files.size() * 2)
01107 << "#" << command << " " << args << "\n";
01108 #endif
01109
01110 if (command == "define") {
01111 handle_define_directive(args, first_line, first_col, first_file);
01112 } else if (command == "undef") {
01113 handle_undef_directive(args, first_line, first_col, first_file);
01114 } else if (command == "ifdef") {
01115 handle_ifdef_directive(args, first_line, first_col, first_file);
01116 } else if (command == "ifndef") {
01117 handle_ifndef_directive(args, first_line, first_col, first_file);
01118 } else if (command == "if") {
01119 handle_if_directive(args, first_line, first_col, first_file);
01120 } else if (command == "else" || command == "elif") {
01121
01122
01123 skip_false_if_block(false);
01124 } else if (command == "endif") {
01125
01126
01127 } else if (command == "include") {
01128 handle_include_directive(args, first_line, first_col, first_file);
01129 } else if (command == "pragma") {
01130
01131 } else if (command == "ident") {
01132
01133 } else if (command == "error") {
01134 handle_error_directive(args, first_line, first_col, first_file);
01135 } else {
01136 warning("Ignoring unknown directive #" + command,
01137 first_line, first_col, first_file);
01138 }
01139
01140 _start_of_line = true;
01141 return '\n';
01142 }
01143
01144
01145
01146
01147
01148
01149 int CPPPreprocessor::
01150 get_preprocessor_command(int c, string &command) {
01151
01152 assert(c == '#');
01153 c = get();
01154
01155
01156
01157 while (c != EOF && (c == ' ' || c == '\t')) {
01158 c = get();
01159 }
01160
01161
01162 while (c != EOF && (isalnum(c) || c == '_')) {
01163 command += c;
01164 c = get();
01165 }
01166
01167 return c;
01168 }
01169
01170
01171
01172
01173
01174
01175 int CPPPreprocessor::
01176 get_preprocessor_args(int c, string &args) {
01177
01178
01179
01180 while (c != EOF && c != '\n') {
01181 if (c == '\\') {
01182 int next_c = get();
01183 if (next_c == '\n') {
01184
01185 args += '\n';
01186 } else {
01187
01188 args += c;
01189 if (next_c != EOF) {
01190 args += next_c;
01191 }
01192 }
01193 } else {
01194 args += c;
01195 }
01196 c = skip_comment(get());
01197 }
01198
01199
01200 args = trim_blanks(args);
01201
01202 return c;
01203 }
01204
01205
01206
01207
01208
01209
01210 void CPPPreprocessor::
01211 handle_define_directive(const string &args, int first_line,
01212 int first_col, const CPPFile &first_file) {
01213 if (args.empty()) {
01214 warning("Ignoring empty #define directive",
01215 first_line, first_col, first_file);
01216 } else {
01217 CPPManifest *manifest = new CPPManifest(args, first_file);
01218 manifest->_vis = preprocessor_vis;
01219 if (!manifest->_has_parameters) {
01220 string expr_string = manifest->expand();
01221 if (!expr_string.empty()) {
01222 manifest->_expr = parse_expr(expr_string, global_scope, global_scope);
01223 }
01224 }
01225 _manifests[manifest->_name] = manifest;
01226 }
01227 }
01228
01229
01230
01231
01232
01233
01234 void CPPPreprocessor::
01235 handle_undef_directive(const string &args, int first_line,
01236 int first_col, const CPPFile &first_file) {
01237 if (args.empty()) {
01238 warning("Ignoring empty #undef directive",
01239 first_line, first_col, first_file);
01240 } else {
01241 Manifests::iterator mi = _manifests.find(args);
01242 if (mi != _manifests.end()) {
01243 _manifests.erase(mi);
01244 }
01245 }
01246 }
01247
01248
01249
01250
01251
01252
01253 void CPPPreprocessor::
01254 handle_ifdef_directive(const string &args, int, int, const CPPFile &) {
01255 Manifests::const_iterator mi = _manifests.find(args);
01256 if (mi != _manifests.end()) {
01257
01258 return;
01259 }
01260
01261
01262 skip_false_if_block(true);
01263 }
01264
01265
01266
01267
01268
01269
01270 void CPPPreprocessor::
01271 handle_ifndef_directive(const string &args, int, int, const CPPFile &) {
01272 Manifests::const_iterator mi = _manifests.find(args);
01273 if (mi == _manifests.end()) {
01274
01275 return;
01276 }
01277
01278
01279 skip_false_if_block(true);
01280 }
01281
01282
01283
01284
01285
01286
01287
01288 void CPPPreprocessor::
01289 handle_if_directive(const string &args, int first_line,
01290 int first_col, const CPPFile &first_file) {
01291 CPPExpression *expr = parse_expr(args, global_scope, global_scope);
01292
01293 int expression_result = 0;
01294
01295 if (expr != (CPPExpression *)NULL) {
01296 CPPExpression::Result result = expr->evaluate();
01297 if (result._type == CPPExpression::RT_error) {
01298 warning("Ignoring invalid expression " + args,
01299 first_line, first_col, first_file);
01300 } else {
01301 expression_result = result.as_integer();
01302 }
01303 } else {
01304 warning("Ignoring invalid expression " + args,
01305 first_line, first_col, first_file);
01306 }
01307
01308 if (expression_result) {
01309
01310 return;
01311 }
01312
01313
01314 skip_false_if_block(true);
01315 }
01316
01317
01318
01319
01320
01321
01322 void CPPPreprocessor::
01323 handle_include_directive(const string &args, int first_line,
01324 int first_col, const CPPFile &first_file) {
01325 bool okflag = false;
01326 Filename filename;
01327 Filename filename_as_referenced;
01328 bool angle_quotes = false;
01329
01330 string expr = args;
01331
01332
01333
01334
01335
01336
01337
01338 if (!expr.empty() && (expr[0] != '"' && expr[0] != '<')) {
01339 expr = expand_manifests(expr);
01340 }
01341
01342 if (!expr.empty()) {
01343 if (expr[0] == '"' && expr[expr.size() - 1] == '"') {
01344 filename = expr.substr(1, expr.size() - 2);
01345 okflag = true;
01346
01347 if (_files.size() == 1) {
01348
01349
01350
01351 _quote_includes.insert(filename);
01352 }
01353 } else if (expr[0] == '<' && expr[expr.size() - 1] == '>') {
01354 filename = expr.substr(1, expr.size() - 2);
01355 angle_quotes = true;
01356 okflag = true;
01357
01358 if (_files.size() == 1) {
01359
01360
01361
01362 _angle_includes.insert(filename);
01363 }
01364 }
01365 }
01366
01367 filename.set_text();
01368 filename_as_referenced = filename;
01369
01370
01371
01372 bool found_file = false;
01373 CPPFile::Source source = CPPFile::S_none;
01374
01375 if (okflag) {
01376 if (!angle_quotes) {
01377 found_file = filename.exists();
01378 source = CPPFile::S_local;
01379 }
01380
01381
01382 if (!found_file && filename.resolve_filename(_system_include_path)) {
01383 found_file = true;
01384 source = CPPFile::S_system;
01385 }
01386
01387 if (!found_file && filename.resolve_filename(_include_path)) {
01388 found_file = true;
01389 source = CPPFile::S_alternate;
01390 }
01391
01392 if (!found_file) {
01393 warning("Cannot find " + filename.get_fullpath(),
01394 first_line, first_col, first_file);
01395 } else {
01396 _last_c = '\0';
01397 if (!push_file(CPPFile(filename, filename_as_referenced, source))) {
01398 warning("Unable to read " + filename.get_fullpath(),
01399 first_line, first_col, first_file);
01400 }
01401 }
01402 } else {
01403 warning("Ignoring invalid #include directive",
01404 first_line, first_col, first_file);
01405 }
01406 }
01407
01408
01409
01410
01411
01412
01413 void CPPPreprocessor::
01414 handle_error_directive(const string &args, int first_line,
01415 int first_col, const CPPFile &first_file) {
01416 error(args, first_line, first_col, first_file);
01417 }
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427 void CPPPreprocessor::
01428 skip_false_if_block(bool consider_elifs) {
01429 int level = 0;
01430 _save_comments = false;
01431
01432 int c = skip_comment(get());
01433 while (c != EOF) {
01434 if (c == '#' && _start_of_line) {
01435 CPPFile first_file = get_file();
01436 int first_line = get_line_number();
01437 int first_col = get_col_number();
01438
01439
01440 string command;
01441 c = get_preprocessor_command(c, command);
01442 if (command == "if" || command == "ifdef" || command == "ifndef") {
01443
01444 level++;
01445 } else if (command == "else") {
01446 if (level == 0 && consider_elifs) {
01447
01448 _save_comments = true;
01449 return;
01450 }
01451 } else if (command == "elif") {
01452 if (level == 0 && consider_elifs) {
01453
01454 _save_comments = true;
01455 string args;
01456 c = get_preprocessor_args(c, args);
01457 handle_if_directive(args, first_line, first_col, first_file);
01458 return;
01459 }
01460 } else if (command == "endif") {
01461 if (level == 0) {
01462
01463 _save_comments = true;
01464 return;
01465 }
01466 level--;
01467 }
01468 } else {
01469 c = skip_comment(get());
01470 }
01471 }
01472
01473 _save_comments = true;
01474 }
01475
01476
01477
01478
01479
01480
01481 CPPToken CPPPreprocessor::
01482 get_quoted_char(int c) {
01483 CPPFile first_file = get_file();
01484 int first_line = get_line_number();
01485 int first_col = get_col_number();
01486 string str = scan_quoted(c);
01487
01488 YYSTYPE result;
01489 if (!str.empty()) {
01490 result.u.integer = (int)str[0];
01491 } else {
01492 result.u.integer = 0;
01493 }
01494 return CPPToken(CHAR, first_line, first_col, first_file, str, result);
01495 }
01496
01497
01498
01499
01500
01501
01502 CPPToken CPPPreprocessor::
01503 get_quoted_string(int c) {
01504 CPPFile first_file = get_file();
01505 int first_line = get_line_number();
01506 int first_col = get_col_number();
01507 string str = scan_quoted(c);
01508 return CPPToken(STRING, first_line, first_col, first_file, str);
01509 }
01510
01511
01512
01513
01514
01515
01516 CPPToken CPPPreprocessor::
01517 get_identifier(int c) {
01518 CPPFile first_file = get_file();
01519 int first_line = get_line_number();
01520 int first_col = get_col_number();
01521 string name(1, (char)c);
01522
01523 c = get();
01524 while (c != EOF && (isalnum(c) || c == '_')) {
01525 name += c;
01526 c = get();
01527 }
01528
01529 _last_c = c;
01530
01531
01532 Manifests::const_iterator mi = _manifests.find(name);
01533 if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) {
01534 return expand_manifest((*mi).second);
01535 }
01536
01537
01538 int kw = check_keyword(name);
01539
01540
01541 switch (kw) {
01542 case KW_BEGIN_PUBLISH:
01543 preprocessor_vis = V_published;
01544 break;
01545
01546 case KW_END_PUBLISH:
01547 preprocessor_vis = V_public;
01548 break;
01549 }
01550
01551 if (kw != 0) {
01552 YYSTYPE result;
01553 result.u.identifier = (CPPIdentifier *)NULL;
01554 return CPPToken(kw, first_line, first_col, first_file, name, result);
01555 }
01556
01557 return CPPToken(SIMPLE_IDENTIFIER, first_line, first_col, first_file,
01558 name);
01559 }
01560
01561
01562
01563
01564
01565
01566 CPPToken CPPPreprocessor::
01567 expand_manifest(const CPPManifest *manifest) {
01568 vector_string args;
01569
01570 if (manifest->_has_parameters) {
01571
01572 extract_manifest_args(manifest->_name, manifest->_num_parameters, args);
01573 }
01574
01575 string expanded = " " + manifest->expand(args) + " ";
01576 push_string(expanded, true);
01577
01578 if (!manifest->_has_parameters) {
01579
01580
01581 _files.back()._ignore_manifest = manifest;
01582 }
01583
01584 #ifdef CPP_VERBOSE_LEX
01585 indent(cerr, _files.size() * 2)
01586 << "Expanding " << manifest->_name << " to " << expanded << "\n";
01587 #endif
01588
01589 return internal_get_next_token();
01590 }
01591
01592
01593
01594
01595
01596
01597 void CPPPreprocessor::
01598 extract_manifest_args(const string &name, int num_args,
01599 vector_string &args) {
01600 CPPFile first_file = get_file();
01601 int first_line = get_line_number();
01602 int first_col = get_col_number();
01603
01604
01605 int c = _last_c;
01606 _last_c = '\0';
01607 while (c != EOF && isspace(c)) {
01608 c = get();
01609 }
01610
01611 if (c != '(') {
01612
01613 string arg;
01614 while (c != EOF && (isalnum(c) || c == '_')) {
01615 arg += c;
01616 c = get();
01617 }
01618 args.push_back(arg);
01619 } else {
01620
01621 c = get();
01622 string arg;
01623 while (c != EOF && c != ')') {
01624 if (c == ',') {
01625 args.push_back(arg);
01626 arg = "";
01627
01628 } else if (c == '(') {
01629
01630 int paren_level = 1;
01631 while (c != EOF && paren_level > 0) {
01632 arg += c;
01633 c = get();
01634 if (c == '(') {
01635 paren_level++;
01636 } else if (c == ')') {
01637 paren_level--;
01638 }
01639 }
01640 if (c != EOF) {
01641 arg += c;
01642 }
01643
01644 } else {
01645 arg += c;
01646 }
01647 c = get();
01648 }
01649 if (num_args != 0 || !arg.empty()) {
01650 args.push_back(arg);
01651 }
01652 }
01653
01654 if ((int)args.size() != num_args) {
01655 warning("Wrong number of arguments for manifest " + name,
01656 first_line, first_col, first_file);
01657 }
01658 }
01659
01660
01661
01662
01663
01664
01665 void CPPPreprocessor::
01666 expand_defined_function(string &expr, size_t q, size_t &p) {
01667 string result;
01668
01669 vector_string args;
01670 extract_manifest_args_inline("defined", 1, args, expr, p);
01671 if (args.size() >= 1) {
01672 const string &manifest_name = args[0];
01673 Manifests::const_iterator mi = _manifests.find(manifest_name);
01674 if (mi != _manifests.end()) {
01675
01676 result = "1";
01677 } else {
01678
01679 result = "0";
01680 }
01681 }
01682
01683 expr = expr.substr(0, q) + result + expr.substr(p);
01684 p = q + result.size();
01685 }
01686
01687
01688
01689
01690
01691
01692 void CPPPreprocessor::
01693 expand_manifest_inline(string &expr, size_t q, size_t &p,
01694 const CPPManifest *manifest) {
01695 vector_string args;
01696 if (manifest->_has_parameters) {
01697 extract_manifest_args_inline(manifest->_name, manifest->_num_parameters,
01698 args, expr, p);
01699 }
01700 string result = manifest->expand(args);
01701
01702 expr = expr.substr(0, q) + result + expr.substr(p);
01703 p = q + result.size();
01704 }
01705
01706
01707
01708
01709
01710
01711 void CPPPreprocessor::
01712 extract_manifest_args_inline(const string &name, int num_args,
01713 vector_string &args,
01714 const string &expr, size_t &p) {
01715
01716 while (p < expr.size() && isspace(expr[p])) {
01717 p++;
01718 }
01719 if (p >= expr.size() || expr[p] != '(') {
01720
01721 size_t q = p;
01722 while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) {
01723 p++;
01724 }
01725 args.push_back(expr.substr(q, p - q));
01726 } else {
01727
01728 p++;
01729 size_t q = p;
01730 while (p < expr.size() && expr[p] != ')') {
01731 if (expr[p] == ',') {
01732 args.push_back(expr.substr(q, p - q));
01733 q = p+1;
01734
01735 } else if (expr[p] == '(') {
01736
01737 int paren_level = 1;
01738 while (p+1 < expr.size() && paren_level > 0) {
01739 p++;
01740 if (expr[p] == '(') {
01741 paren_level++;
01742 } else if (expr[p] == ')') {
01743 paren_level--;
01744 }
01745 }
01746 }
01747 p++;
01748 }
01749 args.push_back(expr.substr(q, p - q));
01750
01751 if (p < expr.size() && expr[p] == ')') {
01752 p++;
01753 }
01754 }
01755
01756 if ((int)args.size() != num_args) {
01757 warning("Wrong number of arguments for manifest " + name);
01758 }
01759 }
01760
01761
01762
01763
01764
01765
01766 CPPToken CPPPreprocessor::
01767 get_number(int c, int c2) {
01768 CPPFile first_file = get_file();
01769 int first_line = get_line_number();
01770 int first_col = get_col_number();
01771
01772 string num(1, (char)c);
01773 bool leading_zero = (c == '0');
01774 bool decimal_point = (c == '.');
01775
01776 if (c2 == 0) {
01777 c = get();
01778 } else {
01779 c = c2;
01780 }
01781 if (leading_zero && c == 'x') {
01782
01783 num += c;
01784 c = get();
01785
01786 while (c != EOF && (isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f'))) {
01787 num += c;
01788 c = get();
01789 }
01790
01791 while (c == 'L' || c == 'U') {
01792
01793 c = get();
01794 }
01795
01796 _last_c = c;
01797
01798 YYSTYPE result;
01799 result.u.integer = strtol(num.c_str(), (char **)NULL, 16);
01800 return CPPToken(INTEGER, first_line, first_col, first_file, num, result);
01801 }
01802
01803 while (c != EOF && isdigit(c)) {
01804 num += c;
01805 c = get();
01806 }
01807
01808 if (c == '.' && !decimal_point) {
01809
01810 decimal_point = true;
01811 num += c;
01812 c = get();
01813
01814 while (c != EOF && isdigit(c)) {
01815 num += c;
01816 c = get();
01817 }
01818 }
01819
01820 if (decimal_point) {
01821 if (tolower(c) == 'e') {
01822
01823 num += c;
01824 c = get();
01825 if (c == '-' || c == '+') {
01826 num += c;
01827 c = get();
01828 }
01829 while (c != EOF && isdigit(c)) {
01830 num += c;
01831 c = get();
01832 }
01833 }
01834
01835 if (c == 'f') {
01836
01837 c = get();
01838 }
01839
01840 _last_c = c;
01841 YYSTYPE result;
01842 result.u.real = strtod(num.c_str(), (char **)NULL);
01843 return CPPToken(REAL, first_line, first_col, first_file, num, result);
01844 }
01845
01846
01847
01848 while (c == 'L' || c == 'U') {
01849
01850 c = get();
01851 }
01852
01853 _last_c = c;
01854 YYSTYPE result;
01855
01856 if (leading_zero) {
01857
01858
01859
01860 result.u.integer = strtol(num.c_str(), (char **)NULL, 8);
01861
01862 } else {
01863
01864 result.u.integer = strtol(num.c_str(), (char **)NULL, 10);
01865 }
01866
01867 return CPPToken(INTEGER, first_line, first_col, first_file, num, result);
01868 }
01869
01870
01871
01872
01873
01874
01875 int CPPPreprocessor::
01876 check_keyword(const string &name) {
01877 if (name == "__begin_publish") return KW_BEGIN_PUBLISH;
01878 if (name == "bool") return KW_BOOL;
01879 if (name == "catch") return KW_CATCH;
01880 if (name == "char") return KW_CHAR;
01881 if (name == "class") return KW_CLASS;
01882 if (name == "const") return KW_CONST;
01883 if (name == "delete") return KW_DELETE;
01884 if (name == "double") return KW_DOUBLE;
01885 if (name == "dynamic_cast") return KW_DYNAMIC_CAST;
01886 if (name == "else") return KW_ELSE;
01887 if (name == "__end_publish") return KW_END_PUBLISH;
01888 if (name == "enum") return KW_ENUM;
01889 if (name == "extern") return KW_EXTERN;
01890 if (name == "explicit") return KW_EXPLICIT;
01891 if (name == "__published") return KW_PUBLISHED;
01892 if (name == "false") return KW_FALSE;
01893 if (name == "float") return KW_FLOAT;
01894 if (name == "friend") return KW_FRIEND;
01895 if (name == "for") return KW_FOR;
01896 if (name == "goto") return KW_GOTO;
01897 if (name == "if") return KW_IF;
01898 if (name == "inline") return KW_INLINE;
01899 if (name == "int") return KW_INT;
01900 if (name == "long") return KW_LONG;
01901 if (name == "mutable") return KW_MUTABLE;
01902 if (name == "namespace") return KW_NAMESPACE;
01903 if (name == "new") return KW_NEW;
01904 if (name == "operator") return KW_OPERATOR;
01905 if (name == "private") return KW_PRIVATE;
01906 if (name == "protected") return KW_PROTECTED;
01907 if (name == "public") return KW_PUBLIC;
01908 if (name == "register") return KW_REGISTER;
01909 if (name == "return") return KW_RETURN;
01910 if (name == "short") return KW_SHORT;
01911 if (name == "signed") return KW_SIGNED;
01912 if (name == "sizeof") return KW_SIZEOF;
01913 if (name == "static") return KW_STATIC;
01914 if (name == "static_cast") return KW_STATIC_CAST;
01915 if (name == "struct") return KW_STRUCT;
01916 if (name == "template") return KW_TEMPLATE;
01917 if (name == "throw") return KW_THROW;
01918 if (name == "true") return KW_TRUE;
01919 if (name == "try") return KW_TRY;
01920 if (name == "typedef") return KW_TYPEDEF;
01921 if (name == "typename") return KW_TYPENAME;
01922 if (name == "union") return KW_UNION;
01923 if (name == "unsigned") return KW_UNSIGNED;
01924 if (name == "using") return KW_USING;
01925 if (name == "virtual") return KW_VIRTUAL;
01926 if (name == "void") return KW_VOID;
01927 if (name == "volatile") return KW_VOLATILE;
01928 if (name == "while") return KW_WHILE;
01929
01930 if (!cpp_longlong_keyword.empty() && name == cpp_longlong_keyword) {
01931 return KW_LONGLONG;
01932 }
01933
01934 return 0;
01935 }
01936
01937
01938
01939
01940
01941
01942 string CPPPreprocessor::
01943 scan_quoted(int c) {
01944 int quote_mark = c;
01945
01946 string str;
01947 c = get();
01948 while (c != EOF && c != '\n' && c != quote_mark) {
01949 if (c == '\\') {
01950
01951 c = get();
01952 switch (c) {
01953 case 'n':
01954 c = '\n';
01955 break;
01956
01957 case 't':
01958 c = '\t';
01959 break;
01960
01961 case 'r':
01962 c = '\r';
01963 break;
01964
01965 case 'x':
01966
01967 c = get();
01968 if (isxdigit(c)) {
01969 int val = hex_val(c);
01970 c = get();
01971 if (isxdigit(c)) {
01972 val = (val << 4) | hex_val(c);
01973 } else {
01974 unget(c);
01975 }
01976 c = val;
01977 }
01978 break;
01979
01980 case '0':
01981 case '1':
01982 case '2':
01983 case '3':
01984 case '4':
01985 case '5':
01986 case '6':
01987 case '7':
01988
01989 {
01990 int val = (c - '0');
01991 c = get();
01992 if (c >= '0' && c <= '7') {
01993 val = (val << 3) | (c - '0');
01994 c = get();
01995 if (c >= '0' && c <= '7') {
01996 val = (val << 3) | (c - '0');
01997 } else {
01998 unget(c);
01999 }
02000 } else {
02001 unget(c);
02002 }
02003 c = val;
02004 }
02005 break;
02006 }
02007 }
02008
02009 str += c;
02010 c = get();
02011 }
02012
02013 if (c != quote_mark) {
02014 warning("Unclosed string");
02015 }
02016 return str;
02017 }
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027 bool CPPPreprocessor::
02028 should_ignore_manifest(const CPPManifest *manifest) const {
02029 Files::const_iterator fi;
02030 for (fi = _files.begin(); fi != _files.end(); ++fi) {
02031 if ((*fi)._ignore_manifest == manifest) {
02032 return true;
02033 }
02034 }
02035
02036 return false;
02037 }
02038
02039
02040
02041
02042
02043
02044
02045
02046 bool CPPPreprocessor::
02047 should_ignore_preprocessor() const {
02048 Files::const_iterator fi;
02049 for (fi = _files.begin(); fi != _files.end(); ++fi) {
02050 if ((*fi)._ignore_manifest != NULL) {
02051 return true;
02052 }
02053 }
02054
02055 return false;
02056 }
02057
02058
02059
02060
02061
02062
02063 int CPPPreprocessor::
02064 get() {
02065 if (_unget != '\0') {
02066 int c = _unget;
02067 _unget = '\0';
02068 return c;
02069 }
02070
02071 if (_files.empty()) {
02072 return EOF;
02073 }
02074
02075 int c = _files.back().get();
02076
02077 while (c == EOF && !_files.empty()) {
02078 #ifdef CPP_VERBOSE_LEX
02079 indent(cerr, _files.size() * 2)
02080 << "End of input stream, restoring to previous input\n";
02081 #endif
02082 int last_c = _files.back()._prev_last_c;
02083 _files.pop_back();
02084
02085 if (last_c != '\0') {
02086 c = last_c;
02087 } else if (!_files.empty()) {
02088 c = _files.back().get();
02089 }
02090 }
02091
02092 if (c == '\n') {
02093 _start_of_line = true;
02094 } else if (!isspace(c) && c != '#') {
02095 _start_of_line = false;
02096 }
02097
02098 return c;
02099 }
02100
02101
02102
02103
02104
02105
02106 void CPPPreprocessor::
02107 unget(int c) {
02108 assert(_unget == '\0');
02109 _unget = c;
02110 }
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122 CPPTemplateParameterList *CPPPreprocessor::
02123 nested_parse_template_instantiation(CPPTemplateScope *scope) {
02124 #ifdef CPP_VERBOSE_LEX
02125 indent(cerr, _files.size() * 2)
02126 << "Beginning nested parse\n";
02127 #endif
02128 assert(scope != NULL);
02129
02130 State old_state = _state;
02131 int old_nesting = _paren_nesting;
02132
02133 const CPPTemplateParameterList &formal_params = scope->_parameters;
02134 CPPTemplateParameterList::Parameters::const_iterator pi;
02135 _angle_bracket_found = false;
02136
02137 CPPToken token = internal_get_next_token();
02138 if (token._token == '>') {
02139 _angle_bracket_found = true;
02140 } else {
02141 _saved_tokens.push_back(token);
02142 }
02143
02144 CPPTemplateParameterList *actual_params = new CPPTemplateParameterList;
02145
02146 for (pi = formal_params._parameters.begin();
02147 pi != formal_params._parameters.end() && !_angle_bracket_found;
02148 ++pi) {
02149 _state = S_nested;
02150 _paren_nesting = 0;
02151
02152 CPPFile first_file = get_file();
02153 int first_line = get_line_number();
02154 int first_col = get_col_number();
02155
02156 CPPDeclaration *decl = (*pi);
02157 if (decl->as_type()) {
02158 _saved_tokens.push_back(CPPToken(START_TYPE));
02159 CPPType *type = ::parse_type(this, current_scope, global_scope);
02160 if (type == NULL) {
02161 warning("Invalid type", first_line, first_col, first_file);
02162 skip_to_end_nested();
02163 type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown));
02164 }
02165 actual_params->_parameters.push_back(type);
02166 } else {
02167 _saved_tokens.push_back(CPPToken(START_CONST_EXPR));
02168 CPPExpression *expr = parse_const_expr(this, current_scope, global_scope);
02169 if (expr == NULL) {
02170 warning("Invalid expression", first_line, first_col, first_file);
02171 skip_to_end_nested();
02172 expr = new CPPExpression(0);
02173 }
02174 actual_params->_parameters.push_back(expr);
02175 }
02176 }
02177
02178 if (!_angle_bracket_found) {
02179 warning("Ignoring extra parameters in template instantiation");
02180 skip_to_angle_bracket();
02181 }
02182
02183 _state = old_state;
02184 _paren_nesting = old_nesting;
02185 _angle_bracket_found = false;
02186
02187 #ifdef CPP_VERBOSE_LEX
02188 indent(cerr, _files.size() * 2)
02189 << "Ending nested parse\n";
02190 #endif
02191 return actual_params;
02192 }
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205 void CPPPreprocessor::
02206 skip_to_end_nested() {
02207 #ifdef CPP_VERBOSE_LEX
02208 indent(cerr, _files.size() * 2)
02209 << "Skipping tokens:\n";
02210 #endif
02211
02212
02213 while (!_saved_tokens.empty() && _saved_tokens.back().is_eof()) {
02214 _saved_tokens.pop_back();
02215 }
02216
02217 while (_state != S_end_nested && _state != S_eof) {
02218 get_next_token();
02219 }
02220
02221 #ifdef CPP_VERBOSE_LEX
02222 indent(cerr, _files.size() * 2)
02223 << "Done skipping tokens.\n";
02224 #endif
02225 }
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235 void CPPPreprocessor::
02236 skip_to_angle_bracket() {
02237 #ifdef CPP_VERBOSE_LEX
02238 indent(cerr, _files.size() * 2)
02239 << "Skipping tokens:\n";
02240 #endif
02241
02242 while (!_angle_bracket_found && _state != S_eof) {
02243 _state = S_nested;
02244 while (_state != S_end_nested && _state != S_eof) {
02245 get_next_token();
02246 }
02247 }
02248
02249
02250 while (!_saved_tokens.empty() && _saved_tokens.back().is_eof()) {
02251 _saved_tokens.pop_back();
02252 }
02253
02254 #ifdef CPP_VERBOSE_LEX
02255 indent(cerr, _files.size() * 2)
02256 << "Done skipping tokens.\n";
02257 #endif
02258 }