~ubuntu-branches/ubuntu/maverick/aspectc++/maverick

« back to all changes in this revision

Viewing changes to Puma/src/cpp/PreMacroExpander.cc

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-04-10 17:40:52 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080410174052-xdnsm7oi8hauyyf1
Tags: 1.0pre4~svn.20080409+dfsg-3
Fix another missing include, this time in Ag++/StdSystem.cc

Show diffs side-by-side

added added

removed removed

Lines of Context:
105
105
    // it is a self-referential macro that has to be put on the black list
106
106
    for (Token *t = (Token*)unit->first (); t; t = (Token*)unit->next (t))
107
107
      if (t->is_identifier ()) {
108
 
        PreMacro *macro = _macroManager->getMacro (t->text ());
 
108
        PreMacro *macro = _macroManager->getMacro (t->dtext ());
109
109
        if (macro && unexpanded.find (macro) == unexpanded.end ())
110
110
          _prescanned->insert (t);
111
111
      }
160
160
        // Search for C++ identifiers and check whether it is a macro.
161
161
        else if (token->is_core ()) 
162
162
        {
163
 
            if ((macro = _macroManager->getMacro (token->text ())))
 
163
            if ((macro = _macroManager->getMacro (token->dtext ())))
164
164
            {
165
165
                // Check whether a macro is allowed to expand.
166
166
                if (state.checkToExpand (token, macro, (TokenStream*) _scanner, 
263
263
            if (! ((--pos >= 0) && (src = _scanner->lookup (pos)))) 
264
264
                    return false;
265
265
            unit  = src->unit ();
266
 
                token = src->current ();
 
266
            token = src->current ();
267
267
        }
268
268
    } while (token->is_whitespace () || token->is_comment ());
269
269
 
271
271
    {
272
272
        // If there is a left parenthesis it is a function-like macro.
273
273
        if (mode) {
274
 
                if (token->is_open ()) 
 
274
            if (token->is_open ()) 
275
275
                return true;
276
276
        }
277
277
        
354
354
void PreMacroExpander::replaceUnchangedArg (int index, Unit* argUnit,
355
355
        PreArgDesc &args, Unit* unit, Token *token, bool varnargs) const
356
356
 {
357
 
    Token* prev = (Token*) unit->prev (token);
358
 
    Token* next = (Token*) unit->next (token);
 
357
    Token* prev = prevPreprocessingToken (token, unit);
 
358
    Token* next = nextPreprocessingToken (token, unit);
359
359
        
360
 
    // It's not an empty argument or an argument too much.
 
360
    // It's not an empty argument or an additional argument.
361
361
    if (index <= args.numArgs ()-1) 
362
362
    {
 
363
        MacroUnit& arg = args.getArg (index);
 
364
    
363
365
        // If no concatenation operator was found the argument has 
364
366
        // to be prescanned before it will be inserted into the unit.
365
367
        // During prescan all macros in the argument will be expanded.
366
368
        
367
 
        if (prev)
368
 
            if (prev->is_macro_op () &&        prev->type () == TOK_MO_HASHHASH) 
369
 
            {
370
 
                // The argument has to be inserted in unit as it is.
371
 
                *argUnit += args.getArg (index);
372
 
                return;
373
 
            }
374
 
            
375
 
        if (next)    
376
 
            if (next->is_macro_op () &&        next->type () == TOK_MO_HASHHASH) 
377
 
            {
378
 
                // The argument has to be inserted in unit as it is.
379
 
                *argUnit += args.getArg (index);
380
 
                return;
381
 
            }
382
 
                
383
 
        // Concatenation operator not found. Prescan the argument.
384
 
        Unit* unit = &prescanArgument (&args.getArg (index));
385
 
        argUnit->move ((Token*)argUnit->last (), *unit);
386
 
        delete unit;
 
369
        if (prev && prev->is_macro_op () && prev->type () == TOK_MO_HASHHASH) 
 
370
        {
 
371
            // The argument has to be inserted in unit as it is.
 
372
            *argUnit += arg;
 
373
            
 
374
            // If the argument consists only of spaces and comments,
 
375
            // then the concat operator can be deleted. Concating X
 
376
            // with spaces and comments results in X.
 
377
            if (onlySpacesAndComments (arg)) 
 
378
            {
 
379
                unit->kill (prev);  // Delete the concat operator.
 
380
            }
 
381
            // The concat operator has a special meaning when placed 
 
382
            // between a comma and a variable argument (see below).
 
383
            else if (index == args.numArgs ()-1) 
 
384
            {
 
385
                // Search the comma.
 
386
                Token* comma = prevPreprocessingToken (prev, unit);
 
387
                if (comma && comma->type () == TOK_COMMA) 
 
388
                {
 
389
                    unit->kill (prev);  // Delete the concat operator.
 
390
                }
 
391
            }
 
392
        }
 
393
        else if (next && next->is_macro_op () && next->type () == TOK_MO_HASHHASH) 
 
394
        {
 
395
            // The argument has to be inserted in unit as it is.
 
396
            *argUnit += arg;
 
397
            
 
398
            // If the argument consists only of spaces and comments,
 
399
            // then the concat operator can be deleted. Concating X
 
400
            // with spaces and comments results in X.
 
401
            if (onlySpacesAndComments (args.getArg (index))) 
 
402
            {
 
403
                unit->kill (next);  // Delete the concat operator.
 
404
            }
 
405
        }
 
406
        else 
 
407
        {        
 
408
            // Concatenation operator not found. Prescan the argument.
 
409
            Unit* unit = &prescanArgument (&arg);
 
410
            argUnit->move ((Token*)argUnit->last (), *unit);
 
411
            delete unit;
 
412
        }
387
413
    } 
388
 
    else if (varnargs) 
 
414
    // Rest argument of a variadic macro.
 
415
    else if (varnargs && prev) 
389
416
    {
390
 
        for (; prev; prev = (Token*) unit->prev (prev)) 
391
 
            if (! prev->is_whitespace () && ! prev->is_comment ()) 
392
 
                    break;
393
 
 
394
 
        if (prev)
395
 
            if (prev->is_macro_op () && prev->type () == TOK_MO_HASHHASH) 
 
417
        // The concat operator has a special meaning when placed 
 
418
        // between a comma and a variable argument. If the variable 
 
419
        // argument is left out when the macro is used, then the 
 
420
        // comma before the concat operator will be deleted.
 
421
        if (prev->is_macro_op () && prev->type () == TOK_MO_HASHHASH) 
 
422
        {
 
423
            // Search the comma.
 
424
            Token* comma = prevPreprocessingToken (prev, unit);
 
425
            if (comma && comma->type () == TOK_COMMA) 
396
426
            {
397
 
                for (prev = (Token*) unit->prev (prev); prev; 
398
 
                     prev = (Token*) unit->prev (prev)) 
399
 
                    if (! prev->is_whitespace () && ! prev->is_comment ())
400
 
                            break;
401
 
                if (prev)
402
 
                    unit->kill (prev);
403
 
                return;
 
427
                unit->kill (comma); // Delete the comma.
404
428
            }
 
429
            unit->kill (prev);  // Delete the concat operator.
 
430
        }
405
431
    }
406
432
 }
407
433
 
408
434
 
 
435
// Get the next non-whitespace non-comment token
 
436
Token* PreMacroExpander::nextPreprocessingToken (Token* token, Unit* unit) const {
 
437
  for (token = (Token*) unit->next (token); token; token = (Token*) unit->next (token)) 
 
438
    if (! token->is_whitespace () && ! token->is_comment ())
 
439
      break;
 
440
  return token;
 
441
}
 
442
 
 
443
 
 
444
// Get the previous non-whitespace non-comment token
 
445
Token* PreMacroExpander::prevPreprocessingToken (Token* token, Unit* unit) const {
 
446
  for (token = (Token*) unit->prev (token); token; token = (Token*) unit->prev (token)) 
 
447
    if (! token->is_whitespace () && ! token->is_comment ())
 
448
      break;
 
449
  return token;
 
450
}
 
451
 
 
452
 
 
453
// Check if the given unit contains only spaces and comments.
 
454
bool PreMacroExpander::onlySpacesAndComments (MacroUnit& unit) const {
 
455
  for (Token* token = (Token*) unit.first (); token; token = (Token*) unit.next (token)) 
 
456
    if (! token->is_whitespace () && ! token->is_comment ())
 
457
      return false;
 
458
  return true;
 
459
}
 
460
 
 
461
 
409
462
// Stringify and replace an argument.
410
463
void PreMacroExpander::replaceStringifiedArg (int index, Unit* unit, 
411
464
                                              PreArgDesc &args) const
455
508
                else if (argUnit->next (token) && argUnit->prev (token))
456
509
                    str << " ";
457
510
            }
458
 
            str << "\"" << std::ends;
 
511
            str << "\"";
459
512
                
460
513
            // Create a new string constant token.
461
514
            _parser->cscanner ().fill_unit (str.str ().c_str (), *unit);
529
582
 
530
583
 
531
584
// Process the concatenation macro operator `##'.
532
 
void PreMacroExpander::processConcatOp (Unit* unit) const {
533
 
  
 
585
void PreMacroExpander::processConcatOp (Unit* unit) const { 
534
586
  Token *token = (Token*)unit->first ();
535
587
  Token *last  = (Token*)0;
536
588
  Token *op    = (Token*)0;
 
589
  
537
590
  // Scan the unit.
538
591
  for (; token; token = (Token*) unit->next (token)) {
539
592
   
553
606
    // handle the normal non-whitespace, non-## tokens
554
607
    if (op) {
555
608
      // transform: last and token have to be concatenated and re-scanned
556
 
      string conc = last->text ().c_str ();
557
 
      conc += token->text ();
 
609
      string conc = last->text ();
 
610
 
 
611
      // Concatenation with "(" is legal for VC
 
612
      if (token->type () != TOK_OPEN_ROUND) {
 
613
        // Form: <x> ## <y>
 
614
        conc += token->text ();
 
615
      }
 
616
      // Else form: <x> ##
558
617
 
559
618
      // Scan the string and fill the unit.
560
619
      Unit tmp;
573
632
      created->location (op->location ());
574
633
      created->macro_generated ();
575
634
      
576
 
      // move the generated token behind the expression <x> ## <y>
577
 
      unit->move (token, tmp);
578
 
      // remove the expression
579
 
      unit->kill (last, token);
 
635
      if (token->type () != TOK_OPEN_ROUND) {
 
636
        // move the generated token behind the expression <x> ## <y>
 
637
        unit->move (token, tmp);
 
638
        // remove the expression
 
639
        unit->kill (last, token);
 
640
      } else {
 
641
        // move the generated token before <y>
 
642
        unit->move_before (token, tmp);
 
643
        // remove previous <x> ##
 
644
        unit->kill (last, op);
 
645
      }
580
646
      
581
647
      // go into the right state for further replacements
582
648
      token = last = created;
600
666
void PreMacroExpander::substituteMacro (PreMacro* macro, PreArgDesc &args) const
601
667
 {
602
668
    // Build a unit from the macro body.
603
 
//    Unit* unit = buildUnit (macro->getBody ());
 
669
    //Unit* unit = buildUnit (macro->getBody ());
604
670
    Unit* unit = new MacroUnit (macro->getBodyUnit (_parser->cscanner ()));
605
671
        
606
672
    // Process the stringification macro operator `#' if this is a
646
712
        if (! args.getArg (0).empty ()) 
647
713
        {
648
714
            // Skip whitespaces and comments.
649
 
            for (token = (Token*) args.getArg (0).first (); token; 
650
 
                 token = (Token*) args.getArg (0).next (token)) 
651
 
                    if (! token->is_whitespace () && ! token->is_comment ())
 
715
            MacroUnit& arg = args.getArg (0);
 
716
            for (token = (Token*) arg.first (); token; token = (Token*) arg.next (token))
 
717
                if (! token->is_whitespace () && ! token->is_comment ())
652
718
                    break;
653
 
        } else 
 
719
        } 
 
720
        else 
654
721
            error = true;
655
722
    } 
656
723
    
673
740
    {
674
741
        // Build a new integer constant token with the value 1
675
742
        // if the macro is defined else 0.
676
 
        if (_macroManager->getMacro (token->text ())) 
 
743
        if (_macroManager->getMacro (token->dtext ())) 
677
744
           _parser->cscanner ().fill_unit ("1", *unit);
678
745
        else
679
746
           _parser->cscanner ().fill_unit ("0", *unit);
681
748
        // Set the macro begin and end tokens.
682
749
        ((MacroUnit*)unit)->MacroBegin (args.beginToken ());
683
750
        ((MacroUnit*)unit)->MacroEnd (args.endToken ());
684
 
    } else
 
751
    } 
 
752
    else
685
753
        error = true;
686
754
 
687
755
    // If a syntax error appeared report it and replace the identifier
731
799
                collectArgs (macro, args);
732
800
            processDefined (macro, args);
733
801
        } 
734
 
        
735
802
        // Check whether the macro name is followed by a left parenthesis.
736
803
        // If found substitute the macro call, else it isn't a macro call.
737
 
        else if (! checkForGoOn ()) {
 
804
        else if (! checkForGoOn ()) 
 
805
        {
738
806
            return false;
739
 
        } else {
 
807
        } 
 
808
        else 
 
809
        {
740
810
            collectArgs (macro, args);
741
811
            substituteMacro (macro, args);
742
812
        }
787
857
                // Another argument found.
788
858
                if (token->is_comma () && depth == 1 && ! (macro->
789
859
                    varArgs () && numArgs == (macro->numArgs () - 1))) {
790
 
                    if (!args_found && has_args) {
791
 
                      args_found = true;
792
 
                      if (! unit) {
793
 
                        args.newArg ();
 
860
                    if (! args_found && has_args) {
 
861
                        args_found = true;
 
862
                        if (! unit) {
 
863
                            args.newArg ();
794
864
                            unit = &args.currArg ();
795
 
                      }
 
865
                        }
796
866
                    }
797
867
                    break;
798
868
                }
805
875
                // Maybe the end of a macro call found.
806
876
                else if (token->is_close ()) {
807
877
                    if (! --depth) {        // All done ?
 
878
                        if (! args_found && has_args) {
 
879
                            args_found = true;
 
880
                            if (! unit) {
 
881
                                args.newArg ();
 
882
                                unit = &args.currArg ();
 
883
                            }
 
884
                        }
808
885
                        args.endToken (token);
809
886
                        break;
810
887
                    }
817
894
                if (has_args) {
818
895
                    if (! unit) {
819
896
                        args.newArg ();
820
 
                            unit = &args.currArg ();
 
897
                        unit = &args.currArg ();
821
898
                    }
822
899
                    unit->append (*((Token*) token->duplicate ()));
823
900
                }