42 #define lengthof(x) (sizeof(x) / sizeof(x[0])) 
   50 #define lastof(x) (&x[lengthof(x) - 1]) 
   68 char *
strecpy(
char *dst, 
const char *src, 
const char *last)
 
   71   while (dst != last && *src != 
'\0') {
 
   76   if (dst == last && *src != 
'\0') {
 
   77     fprintf(stderr, 
"String too long for destination buffer\n");
 
   99 static char *
strecat(
char *dst, 
const char *src, 
const char *last)
 
  102   while (*dst != 
'\0') {
 
  103     if (dst == last) 
return dst;
 
  107   return strecpy(dst, src, last);
 
  114 static inline void free(
const void *ptr)
 
  116   free(const_cast<void *>(ptr));
 
  121 # define PATH_MAX 260 
  134     return strcmp(a, b) < 0;
 
  140 typedef std::map<const char*, StringSet*, StringCompare> 
StringMap;
 
  165     this->
fp = fopen(filename, 
"r");
 
  166     if (this->
fp == NULL) {
 
  167       fprintf(stdout, 
"Could not open %s for reading\n", filename);
 
  170     this->
dirname = strdup(filename);
 
  171     char *last = strrchr(this->
dirname, 
'/');
 
  193     int c = fgetc(this->
fp);
 
  194     return (c == EOF) ? 
'\0' : c;
 
  268     this->
buf = (
char*)malloc(
sizeof(*this->
buf) * this->
buf_len);
 
  319         case '\t': this->
Next(); 
break;
 
  320         case '\r': this->
Next(); 
break;
 
  321         case ' ':  this->
Next(); 
break;
 
  390               char previous_char = 
'\0';
 
  434     KeywordList::const_iterator it = this->
keywords.find(name);
 
  457     this->
buf[count] = 
'\0';
 
  460     this->
string = strdup(this->
buf);
 
  483     this->
buf[count] = 
'\0';
 
  485     this->
string = strdup(this->
buf);
 
  508 const char *
GeneratePath(
const char *dirname, 
const char *filename, 
bool local)
 
  511     if (access(filename, R_OK) == 0) 
return strdup(filename);
 
  515     const char *p = filename;
 
  519         char *s = strrchr(path, 
'/');
 
  520         if (s != NULL) *s = 
'\0';
 
  527     if (access(path, R_OK) == 0) 
return strdup(path);
 
  533     const char *p = filename;
 
  537         char *s = strrchr(path, 
'/');
 
  538         if (s != NULL) *s = 
'\0';
 
  545     if (access(path, R_OK) == 0) 
return strdup(path);
 
  580     if (verbose) fprintf(stderr, 
"!");
 
  583     if (verbose) fprintf(stderr, 
"[%d]", value);
 
  588     if (verbose) fprintf(stderr, 
"(");
 
  591     if (verbose) fprintf(stderr, 
")[%d]", value);
 
  597     if (verbose) fprintf(stderr, 
"0");
 
  599     if (verbose) fprintf(stderr, 
"[0]");
 
  605     if (verbose && first) fprintf(stderr, 
"<assumed true>");
 
  626   if (verbose) fprintf(stderr, 
"defined");
 
  628   if (open) lexer->
Lex();
 
  629   if (verbose) fprintf(stderr, open ? 
"(" : 
" ");
 
  631     if (verbose) fprintf(stderr, 
"%s", lexer->
GetString());
 
  632     value = defines->find(lexer->
GetString()) != defines->end();
 
  635     if (verbose) fprintf(stderr, 
")");
 
  639   if (verbose) fprintf(stderr, 
"[%d]", value);
 
  656     if (verbose) fprintf(stderr, 
" && ");
 
  675     if (verbose) fprintf(stderr, 
" || ");
 
  695 void ScanFile(
const char *filename, 
const char *ext, 
bool header, 
bool verbose)
 
  698   static std::stack<Ignore> ignore;
 
  701     for (StringSet::iterator it = 
_defines.begin(); it != 
_defines.end(); it++) {
 
  702       defines.insert(strdup(*it));
 
  722             if (verbose) fprintf(stderr, 
"%s #include ", filename);
 
  727                 if (verbose) fprintf(stderr, 
"%s", lexer.
GetString());
 
  728                 if (!ignore.empty() && ignore.top() != 
NOT_IGNORE) {
 
  729                   if (verbose) fprintf(stderr, 
" (ignored)");
 
  734                   StringMap::iterator it = 
_headers.find(h);
 
  737                     if (verbose) fprintf(stderr, 
"\n");
 
  740                   StringMap::iterator curfile;
 
  747                     *(strrchr(path, 
'.')) = 
'\0';
 
  749                     curfile = 
_files.find(path);
 
  750                     if (curfile == 
_files.end()) {
 
  755                     for (StringSet::iterator header = it->second->begin(); header != it->second->end(); header++) {
 
  756                       if (curfile->second->find(*header) == curfile->second->end()) curfile->second->insert(strdup(*header));
 
  759                   if (curfile->second->find(h) == curfile->second->end()) curfile->second->insert(strdup(h));
 
  769             if (verbose) fprintf(stderr, 
"%s #define ", filename);
 
  772               if (verbose) fprintf(stderr, 
"%s", lexer.
GetString());
 
  773               if (!ignore.empty() && ignore.top() != 
NOT_IGNORE) {
 
  774                 if (verbose) fprintf(stderr, 
" (ignored)");
 
  777               if (defines.find(lexer.
GetString()) == defines.end()) defines.insert(strdup(lexer.
GetString()));
 
  783             if (verbose) fprintf(stderr, 
"%s #undef ", filename);
 
  786               if (verbose) fprintf(stderr, 
"%s", lexer.
GetString());
 
  787               if (!ignore.empty() && ignore.top() != 
NOT_IGNORE) {
 
  788                 if (verbose) fprintf(stderr, 
" (ignored)");
 
  791               StringSet::iterator it = defines.find(lexer.
GetString());
 
  792               if (it != defines.end()) {
 
  801             if (verbose) fprintf(stderr, 
"%s #endif", filename);
 
  803             if (!ignore.empty()) ignore.pop();
 
  804             if (verbose) fprintf(stderr, 
" -> %signore", (!ignore.empty() && ignore.top() != 
NOT_IGNORE) ? 
"" : 
"not ");
 
  808             if (verbose) fprintf(stderr, 
"%s #else", filename);
 
  811             if (!ignore.empty()) ignore.pop();
 
  812             if (ignore.empty() || ignore.top() == 
NOT_IGNORE) {
 
  817             if (verbose) fprintf(stderr, 
" -> %signore", (!ignore.empty() && ignore.top() != 
NOT_IGNORE) ? 
"" : 
"not ");
 
  822             if (verbose) fprintf(stderr, 
"%s #elif ", filename);
 
  825             if (!ignore.empty()) ignore.pop();
 
  826             if (ignore.empty() || ignore.top() == 
NOT_IGNORE) {
 
  832             if (verbose) fprintf(stderr, 
" -> %signore", (!ignore.empty() && ignore.top() != 
NOT_IGNORE) ? 
"" : 
"not ");
 
  837             if (verbose) fprintf(stderr, 
"%s #if ", filename);
 
  839             if (ignore.empty() || ignore.top() == 
NOT_IGNORE) {
 
  845             if (verbose) fprintf(stderr, 
" -> %signore", (!ignore.empty() && ignore.top() != 
NOT_IGNORE) ? 
"" : 
"not ");
 
  850             if (verbose) fprintf(stderr, 
"%s #ifdef ", filename);
 
  853               bool value = defines.find(lexer.
GetString()) != defines.end();
 
  854               if (verbose) fprintf(stderr, 
"%s[%d]", lexer.
GetString(), value);
 
  855               if (ignore.empty() || ignore.top() == 
NOT_IGNORE) {
 
  861             if (verbose) fprintf(stderr, 
" -> %signore", (!ignore.empty() && ignore.top() != 
NOT_IGNORE) ? 
"" : 
"not ");
 
  865             if (verbose) fprintf(stderr, 
"%s #ifndef ", filename);
 
  868               bool value = defines.find(lexer.
GetString()) != defines.end();
 
  869               if (verbose) fprintf(stderr, 
"%s[%d]", lexer.
GetString(), value);
 
  870               if (ignore.empty() || ignore.top() == 
NOT_IGNORE) {
 
  876             if (verbose) fprintf(stderr, 
" -> %signore", (!ignore.empty() && ignore.top() != 
NOT_IGNORE) ? 
"" : 
"not ");
 
  880             if (verbose) fprintf(stderr, 
"%s #<unknown>", filename);
 
  884         if (verbose) fprintf(stderr, 
"\n");
 
  895     for (StringSet::iterator it = defines.begin(); it != defines.end(); it++) {
 
  899     while (!ignore.empty()) ignore.pop();
 
  909 int main(
int argc, 
char *argv[])
 
  911   bool ignorenext = 
true;
 
  912   char *filename = NULL;
 
  914   char *delimiter = NULL;
 
  916   bool verbose = 
false;
 
  918   for (
int i = 0; i < argc; i++) {
 
  923     if (argv[i][0] == 
'-') {
 
  925       if (strncmp(argv[i], 
"-a", 2) == 0) append = 
true;
 
  927       if (strncmp(argv[i], 
"-I", 2) == 0) {
 
  928         if (argv[i][2] == 
'\0') {
 
  937       if (strncmp(argv[i], 
"-D", 2) == 0) {
 
  938         char *p = strchr(argv[i], 
'=');
 
  939         if (p != NULL) *p = 
'\0';
 
  940         _defines.insert(strdup(&argv[i][2]));
 
  944       if (strncmp(argv[i], 
"-f", 2) == 0) {
 
  945         if (filename != NULL) 
continue;
 
  946         filename = strdup(&argv[i][2]);
 
  950       if (strncmp(argv[i], 
"-o", 2) == 0) {
 
  951         if (ext != NULL) 
continue;
 
  952         ext = strdup(&argv[i][2]);
 
  956       if (strncmp(argv[i], 
"-s", 2) == 0) {
 
  957         if (delimiter != NULL) 
continue;
 
  958         delimiter = strdup(&argv[i][2]);
 
  962       if (strncmp(argv[i], 
"-v", 2) == 0) verbose = 
true;
 
  965     ScanFile(argv[i], ext, 
false, verbose);
 
  969   if (filename == NULL) filename = strdup(
"Makefile");
 
  972   if (delimiter == NULL) delimiter = strdup(
"# DO NOT DELETE");
 
  978   char *content = NULL;
 
  983   FILE *src = fopen(filename, 
"rb");
 
  985     fseek(src, 0, SEEK_END);
 
  986     if ((size = ftell(src)) < 0) {
 
  987       fprintf(stderr, 
"Could not read %s\n", filename);
 
  991     content = (
char*)malloc(size * 
sizeof(*content));
 
  992     if (fread(content, 1, size, src) != (size_t)size) {
 
  993       fprintf(stderr, 
"Could not read %s\n", filename);
 
  999   FILE *dst = fopen(filename, 
"w");
 
 1000   bool found_delimiter = 
false;
 
 1003     src = fopen(backup, 
"wb");
 
 1004     if (fwrite(content, 1, size, src) != (
size_t)size) {
 
 1005       fprintf(stderr, 
"Could not write %s\n", filename);
 
 1011     src = fopen(backup, 
"rb");
 
 1012     while (fgets(content, size, src) != NULL) {
 
 1013       fputs(content, dst);
 
 1014       if (!strncmp(content, delimiter, strlen(delimiter))) found_delimiter = 
true;
 
 1015       if (!append && found_delimiter) 
break;
 
 1019   if (!found_delimiter) fprintf(dst, 
"\n%s\n", delimiter);
 
 1021   for (StringMap::iterator it = 
_files.begin(); it != 
_files.end(); it++) {
 
 1022     for (StringSet::iterator h = it->second->begin(); h != it->second->end(); h++) {
 
 1023       fprintf(dst, 
"%s: %s\n", it->first, *h);
 
 1035   for (StringMap::iterator it = 
_files.begin(); it != 
_files.end(); it++) {
 
 1036     for (StringSet::iterator h = it->second->begin(); h != it->second->end(); h++) {
 
 1039     it->second->clear();
 
 1045   for (StringMap::iterator it = 
_headers.begin(); it != 
_headers.end(); it++) {
 
 1046     for (StringSet::iterator h = it->second->begin(); h != it->second->end(); h++) {
 
 1049     it->second->clear();
 
 1055   for (StringSet::iterator it = 
_defines.begin(); it != 
_defines.end(); it++) {