openrave.org

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cpp-gen-md5.cpp
Go to the documentation of this file.
1 
17 #include "cpp_lexer.hpp"
18 
19 #include <iostream>
20 #include <vector>
21 #include <sstream>
22 #include <cstdio>
23 #include <cstring>
24 
25 #include "md5.h"
26 
27 using namespace std;
28 
29 void getTokenData(const char* fname, vector<char>& vdata);
30 string getmd5hash(const char* fname, const vector<char>& vbasedata);
31 
32 int main(int argc, char* argv[])
33 {
34  if( argc < 2 ) {
35  cerr << "No filename given" << endl
36  << "cpp-gen-md5 [common-string] [shared-filename] [filename1 define1] [filename2 define2]* ..." << endl
37  << "Generates a md5 sum from the lexical tokens of a C++ ignoring directives and whitespace." << endl
38  << "If only a filename is given, will output a 16 byte string" << endl
39  << "If both filename and define are given will output #define @define2@ \"@md5hash@\"" << endl;
40  return 2;
41  }
42 
43  vector<char> vbasedata;
44  vbasedata.resize(strlen(argv[1]));
45  if( vbasedata.size() > 0 ) {
46  memcpy(&vbasedata[0],argv[1],vbasedata.size());
47  }
48  if( strlen(argv[2]) > 0 ) {
49  getTokenData(argv[2],vbasedata);
50  }
51  for(int i = 3; i < argc; i += 2) {
52  vector<char> vdata=vbasedata;
53  string md5hash = getmd5hash(argv[i],vdata);
54  if( md5hash == "" ) {
55  return 1;
56  }
57  if( i+1 < argc ) {
58  cout << "#define " << argv[i+1] << " \"" << md5hash << "\"" << endl;
59  }
60  else {
61  cout << md5hash << endl;
62  }
63  }
64 
65  return 0;
66 }
67 
68 void getTokenData(const char* fname,vector<char>& vdata)
69 {
70  // Read the input file into a buffer.
71  FILE* f = fopen(fname, "rb");
72  if (!f) {
73  cerr << "Cannot open input file: " << fname << endl;
74  return;
75  }
76 
77  fseek(f, 0, SEEK_END);
78  int const size = ftell(f);
79  fseek(f, 0, SEEK_SET);
80  vector<char> buf(size);
81  size_t read = fread(&buf[0], 1, size, f);
82  fclose(f);
83  if( read == 0 || read != size ) {
84  return;
85  }
86 
87  cpp::clearstate();
88  cpp::lexer_iterator first(cpp::NewLexer(&buf[0], &buf[0]+buf.size(), fname));
89  cpp::lexer_iterator last;
90 
91  while (first != last) {
92  cpp::Token const& token = *first;
93  switch(token.id) {
94  case cpp::Unknown_token:
95  case cpp::Directive_token:
96  case cpp::EOL_token:
97  case cpp::EOF_token:
98  case cpp::Comment_token:
99  break;
100  default:
101  vdata.push_back(token.id&0xff);
102  if( token.id&0xffff00) {
103  vdata.push_back((token.id>>8)&0xff);
104  vdata.push_back((token.id>>16)&0xff);
105  }
106  vdata.push_back((token.id>>24)&0xff);
107  //cpp::PrintToken(token);
108  if( (token.id&cpp::TokenTypeMask) == cpp::OperatorTokenType ) {
109  break;
110  }
111  if( (token.id&cpp::TokenTypeMask) == cpp::IdentifierTokenType ) {
112  if (token.id < cpp::Kwd_last) {
113  break;
114  }
115  }
116  for(size_t i = 0; i < token.text.size(); ++i) {
117  vdata.push_back(token.text[i]);
118  }
119  }
120 
121  ++first;
122  }
123 }
124 
125 string getmd5hash(const char* fname, const vector<char>& vbasedata)
126 {
127  vector<char> vdata = vbasedata;
128  vdata.reserve(vdata.capacity()+10000);
129  getTokenData(fname,vdata);
130 
131  md5_state_t state;
132  md5_byte_t digest[16];
133 
134  md5_init(&state);
135  md5_append(&state, (const md5_byte_t *)&vdata[0], vdata.size());
136  md5_finish(&state, digest);
137  char hex_output[16*2+1];
138  for (int di = 0; di < 16; ++di) {
139  sprintf(hex_output + di * 2, "%02x", digest[di]);
140  }
141  return string(hex_output);
142 }