~ubuntu-branches/ubuntu/quantal/aspectc++/quantal

« back to all changes in this revision

Viewing changes to Puma/examples/macronames/macronames.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:
 
1
#include "Puma/CCParser.h"
 
2
#include "Puma/ErrorStream.h"
 
3
#include "Puma/UnitIterator.h"
 
4
#include "Puma/CTokens.h"
 
5
#include "Puma/PreParser.h"
 
6
#include <iostream>
 
7
#include <map>
 
8
#include <set>
 
9
 
 
10
typedef std::set<int> LineNumbers;
 
11
typedef std::map<const char*,LineNumbers> Macros;
 
12
 
 
13
 
 
14
int main (int argc, char **argv) {
 
15
  if (argc < 2) {
 
16
    std::cout << "Extract C preprocessor macro names from a file" << std::endl;
 
17
    std::cout << "usage: macronames <filename>" << std::endl;
 
18
    return 1;
 
19
  }
 
20
 
 
21
  // scan input file
 
22
  Puma::ErrorStream err;
 
23
  Puma::CProject project(err, argc, argv);
 
24
  Puma::Unit *file = project.scanFile(argv[argc-1]);
 
25
  if (! file) {
 
26
    std::cerr << argv[argc-1] << ": unable to scan input file" << std::endl;
 
27
    return 1;
 
28
  }
 
29
 
 
30
  // find macro names in the token lists of #if, #elseif, 
 
31
  // #ifdef, and #ifndef directives
 
32
  Macros macros;
 
33
  Puma::UnitIterator token(*file);
 
34
  for (; *token; ++token) {
 
35
    if (token->is_preprocessor()) { 
 
36
      int type = token->type();
 
37
      if (type == TOK_PRE_IF || type == TOK_PRE_ELIF) {
 
38
        // search for identifiers, ignore special identifier "defined"
 
39
        int line = token->location().line();
 
40
        for (++token; *token; ++token) {
 
41
          if (token->is_whitespace()) {
 
42
            // white space, let's see if it is the end of the directive
 
43
            const char *c = token->text().c_str();
 
44
            for (; *c && *c != '\n'; c++);
 
45
            if (*c == '\n') {
 
46
              // end of directive, stop searching for macro names
 
47
              break;
 
48
            }
 
49
          } else if (token->is_identifier() && strcmp(token->text().c_str(), "defined") != 0) {
 
50
            // macro name found
 
51
            macros[token->text().c_str()].insert(token->location().line());
 
52
          }
 
53
        }
 
54
      } else if (type == TOK_PRE_IFDEF || type == TOK_PRE_IFNDEF) {
 
55
        // skip comments and white spaces
 
56
        for (++token; *token && (token->is_comment() || token->is_whitespace()); ++token);
 
57
        if (*token && token->is_identifier()) {
 
58
          // macro name found
 
59
          macros[token->text().c_str()].insert(token->location().line());
 
60
        }
 
61
      }
 
62
    }
 
63
  }
 
64
  
 
65
  // print the macro names and the line numbers where they are called (XML)
 
66
  std::cout << "<?xml version=\"1.0\"?>\n<macros>" << std::endl;
 
67
  Macros::const_iterator macro = macros.begin();
 
68
  for (; macro != macros.end(); ++macro) {
 
69
    std::cout << "  <macro name=\"" << macro->first << "\">" << std::endl;
 
70
    LineNumbers::const_iterator number = macro->second.begin();
 
71
    for (; number != macro->second.end(); ++number) {
 
72
      std::cout << "    <line>" << *number << "</line>" << std::endl;
 
73
    }
 
74
    std::cout << "  </macro>" << std::endl;
 
75
  }
 
76
  std::cout << "</macros>" << std::endl;
 
77
  
 
78
  return 0;
 
79
}