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++) {