diff --git a/zsnes/src/Makefile.in b/zsnes/src/Makefile.in index e1d1b26e..1393b470 100644 --- a/zsnes/src/Makefile.in +++ b/zsnes/src/Makefile.in @@ -119,7 +119,7 @@ extraext: ${TOOLSOBJ} @CXX@ @CFLAGS@ -o ${TOOLSDIR}/extraext ${TOOLSDIR}/extraext.cpp ${TOOLSOBJ} sec-test: ${TOOLSOBJ} - @CXX@ @CFLAGS@ -o ${TOOLSDIR}/sec-test ${TOOLSDIR}/sec-test.cpp ${TOOLSDIR}/fileutil.o + @CXX@ @CFLAGS@ -o ${TOOLSDIR}/sec-test ${TOOLSDIR}/sec-test.cpp ${TOOLSOBJ} srccount: ${TOOLSOBJ} @CXX@ @CFLAGS@ -o ${TOOLSDIR}/srccount ${TOOLSDIR}/srccount.cpp ${TOOLSDIR}/fileutil.o diff --git a/zsnes/src/tools/sec-test.cpp b/zsnes/src/tools/sec-test.cpp index 1ee70998..2e057dad 100644 --- a/zsnes/src/tools/sec-test.cpp +++ b/zsnes/src/tools/sec-test.cpp @@ -21,44 +21,128 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. This is part of a toolkit used to assist in ZSNES development This program tells us is a variable is declared in the wrong section. +Or if code is not in an executable section. */ #include #include +#include "strutil.h" using namespace std; #include "fileutil.h" #define LINE_LENGTH 500 + + +bool contains_resx(const char *str) +{ + return(!strncmp(str, "resd ", strlen("resd ")) || + !strncmp(str, "resw ", strlen("resw ")) || + !strncmp(str, "resb ", strlen("resb ")) || + strstr(str, " resd ") || + strstr(str, " resw ") || + strstr(str, " resb ") || + strstr(str, ",resd ") || + strstr(str, ",resw ") || + strstr(str, ",resb ")); +} + +bool contains_dx(const char *str) +{ + return(!strncmp(str, "dd ", strlen("dd ")) || + !strncmp(str, "dw ", strlen("dw ")) || + !strncmp(str, "db ", strlen("db ")) || + strstr(str, " dd ") || + strstr(str, " dw ") || + strstr(str, " db ") || + strstr(str, ",dd ") || + strstr(str, ",dw ") || + strstr(str, ",db ")); +} + +bool label(const char *str) +{ + return(!strchr(str, ' ') && !strchr(str, '\t') && (str[strlen(str)-1] == ':')); +} + void handle_file(const char *filename) { - enum sections { sec_unknown, sec_bss, sec_data, sec_text }; + enum sections { sec_unknown, sec_bss, sec_data, sec_text, sec_macro }; ifstream file(filename, ios::in); if (file) { - char line[LINE_LENGTH]; - sections cur_section = sec_unknown; - for (size_t i = 0; file.getline(line, LINE_LENGTH); i++) + char buffer[LINE_LENGTH]; + sections cur_section = sec_unknown, prev_section = sec_unknown; + for (size_t i = 1; file.getline(buffer, LINE_LENGTH); i++) { - if (!strcasecmp(line, "SECTION .BSS")) { cur_section = sec_bss; } - if (!strcasecmp(line, "SECTION .DATA")) { cur_section = sec_data; } - if (!strcasecmp(line, "SECTION .text")) { cur_section = sec_text; } + char *line = buffer; + + char *comment_p = strchr(line, ';'); + if (comment_p) { *comment_p = 0; } - if ((cur_section != sec_bss) && - (strstr(line, " resd ") || strstr(line, " resw ") || strstr(line, " resb ") || - (strstr(line, ",resd ") || strstr(line, ",resw ") || strstr(line, ",resb ")) )) + if (all_whitespace(line)) { continue; } + + for (char *p = line+strlen(line)-1; isspace(*p); p--) { *p = 0; } + while (isspace(*line)) { line++; } + + + if (!strcasecmp(line, "SECTION .BSS")) + { + prev_section = cur_section; + cur_section = sec_bss; + continue; + } + + if (!strcasecmp(line, "SECTION .DATA")) + { + prev_section = cur_section; + cur_section = sec_data; + continue; + } + + if (!strcasecmp(line, "SECTION .text")) + { + prev_section = cur_section; + cur_section = sec_text; + continue; + } + + if (!strncmp(line, "%macro", strlen("%macro")) || + !strncmp(line, "%imacro", strlen("%imacro"))) + { + prev_section = cur_section; + cur_section = sec_macro; + continue; + } + + if (!strncmp(line, "%endmacro", strlen("%endmacro"))) + { + cur_section = prev_section; + continue; + } + + + if ((cur_section != sec_bss) && contains_resx(line)) { cout << filename << ": line " << i << ": Error, resx in non BSS section. \"" << line << "\"" << endl; } - if ((cur_section != sec_data) && - (strstr(line, " dd ") || strstr(line, " dw ") || strstr(line, " db ") || - (strstr(line, ",dd ") || strstr(line, ",dw ") || strstr(line, ",db ")) )) + if ((cur_section != sec_data) && contains_dx(line)) { cout << filename << ": line " << i << ": Error, dx in non DATA section. \"" << line << "\"" << endl; } + + if ((cur_section != sec_text) && (cur_section != sec_macro)) + { + if (!contains_resx(line) && !contains_dx(line) && !label(line) && + !strstr(line, "NEWSYM") && !strstr(line, "EXTSYM") && !strstr(line, " equ ") && + (*line != '%') && !strstr(line, "ALIGN") && strncmp(line, "bits ", strlen("bits "))) + { + cout << filename << ": line " << i << ": Error, code in non TEXT section. \"" << line << "\"" << endl; + } + } } } else diff --git a/zsnes/src/tools/strutil.cpp b/zsnes/src/tools/strutil.cpp index 6068ba17..201b2b50 100644 --- a/zsnes/src/tools/strutil.cpp +++ b/zsnes/src/tools/strutil.cpp @@ -44,3 +44,15 @@ void Tokenize(const string& str, vector& tokens, const string& delimiter pos = str.find_first_of(delimiters, lastPos); } } + +bool all_whitespace(const char *str) +{ + for (; *str; str++) + { + if (!isspace(*str)) + { + return(false); + } + } + return(true); +} diff --git a/zsnes/src/tools/strutil.h b/zsnes/src/tools/strutil.h index c3427671..9c953380 100644 --- a/zsnes/src/tools/strutil.h +++ b/zsnes/src/tools/strutil.h @@ -28,5 +28,6 @@ This is part of a toolkit used to assist in ZSNES development #include void Tokenize(const std::string&, std::vector&, const std::string&); +bool all_whitespace(const char *); #endif