summaryrefslogtreecommitdiff
path: root/src/map/script.c
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2013-08-27 08:08:34 +0200
committerHaru <haru@dotalux.com>2013-11-05 04:17:39 +0100
commit97001710c06ed7053d18c8baaac602eb563b64b3 (patch)
treea4f08884917a5934e9b7ba66b39cd5e25db92e54 /src/map/script.c
parent0a5abb6de766be6a5068da08eb6477e343f2d7b3 (diff)
downloadhercules-97001710c06ed7053d18c8baaac602eb563b64b3.tar.gz
hercules-97001710c06ed7053d18c8baaac602eb563b64b3.tar.bz2
hercules-97001710c06ed7053d18c8baaac602eb563b64b3.tar.xz
hercules-97001710c06ed7053d18c8baaac602eb563b64b3.zip
Introducing the Hercules Standalone Script Syntax Checker
- Added a command line argument '--script-check' to check a script's syntax without running the server (and without requiring a SQL connection). Usage: ./map-server --script-check /path/to/the/script.txt - For convenience, a script-checker bash script is provided, to set the path correctly when called from a different directory. Usage: /path/to/Hercules/script-checker /path/to/the/script/to/check.txt - While the script checker will supposedly work under windows as well, no convenience scripts are currently provided for platforms other than UNIX (feel free to open a pull request with a .bat launcher or whatever you like) - Integration with IDEs or text editors is possible. In fact, I already have a fully functional plugin for vim (through vim-syntastic), and if there's enough interest, I'll publish it. - screenshot: http://d.pr/i/NOBD - If you want an online checker, http://haru.ws/scriptchecker/ is running this code, without modifications and will be kept up to date (without any warranty though.) - Special thanks to Ind, Yommy, Streusel, who helped making this possible, in a way or another.
Diffstat (limited to 'src/map/script.c')
-rw-r--r--src/map/script.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/src/map/script.c b/src/map/script.c
index 3b0557235..ea3867083 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -1863,66 +1863,98 @@ void read_constdb(void) {
fclose(fp);
}
+// Standard UNIX tab size is 8
+#define TAB_SIZE 8
+#define update_tabstop(tabstop,chars) \
+ do { \
+ (tabstop) -= (chars); \
+ while ((tabstop) <= 0) (tabstop) += TAB_SIZE; \
+ } while (false)
+
/*==========================================
* Display emplacement line of script
*------------------------------------------*/
const char* script_print_line(StringBuf* buf, const char* p, const char* mark, int line)
{
- int i;
+ int i, mark_pos = 0, tabstop = TAB_SIZE;
if( p == NULL || !p[0] ) return NULL;
if( line < 0 )
- StrBuf->Printf(buf, "*% 5d : ", -line);
+ StrBuf->Printf(buf, "*%5d: ", -line); // len = 8
else
- StrBuf->Printf(buf, " % 5d : ", line);
- for(i=0;p[i] && p[i] != '\n';i++){
- if(p + i != mark)
- StrBuf->Printf(buf, "%c", p[i]);
+ StrBuf->Printf(buf, " %5d: ", line); // len = 8
+ update_tabstop(tabstop,8); // len = 8
+ for( i=0; p[i] && p[i] != '\n'; i++ ) {
+ char c = p[i];
+ int w = 1;
+ // Like Clang does, let's print the code with tabs expanded to spaces to ensure that the marker will be under the right character
+ if( c == '\t' ) {
+ c = ' ';
+ w = tabstop;
+ }
+ update_tabstop(tabstop, w);
+ if( p + i < mark)
+ mark_pos += w;
+ if( p + i != mark)
+ StrBuf->Printf(buf, "%*c", w, c);
else
- StrBuf->Printf(buf, "\'%c\'", p[i]);
+ StrBuf->Printf(buf, CL_BT_RED"%*c"CL_RESET, w, c);
}
StrBuf->AppendStr(buf, "\n");
+ if( mark ) {
+ StrBuf->AppendStr(buf, " "CL_BT_CYAN); // len = 8
+ for( ; mark_pos > 0; mark_pos-- ) {
+ StrBuf->AppendStr(buf, "~");
+ }
+ StrBuf->AppendStr(buf, CL_RESET CL_BT_GREEN"^"CL_RESET"\n");
+ }
return p+i+(p[i] == '\n' ? 1 : 0);
}
+#undef TAB_SIZE
+#undef update_tabstop
+#define CONTEXTLINES 3
void script_errorwarning_sub(StringBuf *buf, const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
// Find the line where the error occurred
int j;
int line = start_line;
- const char *p;
- const char *linestart[5] = { NULL, NULL, NULL, NULL, NULL };
+ const char *p, *error_linepos;
+ const char *linestart[CONTEXTLINES];
+ memset(linestart, '\0', sizeof(linestart));
for(p=src;p && *p;line++){
const char *lineend=strchr(p,'\n');
if(lineend==NULL || error_pos<lineend){
break;
}
- for( j = 0; j < 4; j++ ) {
+ for( j = 0; j < CONTEXTLINES-1; j++ ) {
linestart[j] = linestart[j+1];
}
- linestart[4] = p;
- p=lineend+1;
+ linestart[CONTEXTLINES-1] = p;
+ p = lineend+1;
}
+ error_linepos = p;
if( line >= 0 )
- StrBuf->Printf(buf, "script error in file '%s' line %d\n", file, line);
+ StrBuf->Printf(buf, "script error in file '%s' line %d column %d\n", file, line, error_pos-error_linepos+1);
else
StrBuf->Printf(buf, "script error in file '%s' item ID %d\n", file, -line);
StrBuf->Printf(buf, " %s\n", error_msg);
- for(j = 0; j < 5; j++ ) {
- script->print_line(buf, linestart[j], NULL, line + j - 5);
+ for(j = 0; j < CONTEXTLINES; j++ ) {
+ script->print_line(buf, linestart[j], NULL, line + j - CONTEXTLINES);
}
p = script->print_line(buf, p, error_pos, -line);
- for(j = 0; j < 5; j++) {
+ for(j = 0; j < CONTEXTLINES; j++) {
p = script->print_line(buf, p, NULL, line + j + 1 );
}
}
+#undef CONTEXTLINES
void script_error(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
StringBuf buf;
StrBuf->Init(&buf);
- StrBuf->AppendStr(&buf, "\a\n");
+ StrBuf->AppendStr(&buf, "\a");
script->errorwarning_sub(&buf, src, file, start_line, error_msg, error_pos);
@@ -3694,7 +3726,7 @@ void do_final_script(void) {
/*==========================================
* Initialization
*------------------------------------------*/
-void do_init_script(void) {
+void do_init_script(bool minimal) {
script->st_db = idb_alloc(DB_OPT_BASE);
script->userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0);
script->autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0);
@@ -3707,6 +3739,10 @@ void do_init_script(void) {
script->parse_builtin();
script->read_constdb();
+
+ if (minimal)
+ return;
+
mapreg->init();
}