Skip to content

Commit 04daea8

Browse files
committed
Full call stack for DLL interface
1 parent 12e3732 commit 04daea8

File tree

5 files changed

+112
-68
lines changed

5 files changed

+112
-68
lines changed

src/asar-dll-bindings/c/asardll.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@
99
#include <stddef.h> // for size_t
1010

1111
// These structures are returned from various functions
12+
struct stackentry {
13+
const char * fullpath;
14+
const char * prettypath;
15+
int lineno;
16+
const char * details;
17+
};
18+
1219
struct errordata {
1320
const char * fullerrdata;
1421
const char * rawerrdata;
1522
const char * block;
1623
const char * filename;
1724
int line;
18-
const char * callerfilename;
19-
int callerline;
25+
const struct stackentry * callstack;
26+
int callstacksize;
2027
const char * errname;
2128
};
2229

src/asar/asar.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ struct callstack_entry {
161161
};
162162

163163

164+
struct printable_callstack_entry {
165+
string fullpath;
166+
string prettypath;
167+
int lineno;
168+
string details;
169+
};
170+
171+
164172
extern autoarray<callstack_entry> callstack;
165173
extern bool simple_callstacks;
166174

@@ -182,11 +190,7 @@ const char* get_current_file_name();
182190
int get_current_line();
183191
const char* get_current_block();
184192

185-
// RPG Hacker: We only need to keep these two functions around
186-
// until we bump the DLL API version number and update the
187-
// interface to make use of the full callstack.
188-
const char* get_previous_file_name();
189-
int get_previous_file_line_no();
193+
void get_full_printable_callstack(autoarray<printable_callstack_entry>* out, int indentation, bool add_lines);
190194

191195
#if !defined(NO_USE_THREADS) && !defined(RUN_VIA_THREAD)
192196
// RPG Hacker: This is currently disabled for debug builds, because it causes random crashes

src/asar/interface-lib.cpp

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ struct patchparams_base {
3434
int structsize;
3535
};
3636

37+
38+
/* $EXPORTSTRUCT$
39+
*/
40+
struct stackentry {
41+
const char * fullpath;
42+
const char * prettypath;
43+
int lineno;
44+
const char * details;
45+
};
46+
3747
/* $EXPORTSTRUCT$
3848
*/
3949
struct errordata {
@@ -42,8 +52,8 @@ struct errordata {
4252
const char * block;
4353
const char * filename;
4454
int line;
45-
const char * callerfilename;
46-
int callerline;
55+
const struct stackentry * callstack;
56+
int callstacksize;
4757
const char * errname;
4858
};
4959
static autoarray<errordata> errors;
@@ -100,11 +110,23 @@ static void fillerror(errordata& myerr, const char* errname, const char * type,
100110
string details;
101111
get_current_line_details(&location, &details);
102112
myerr.fullerrdata= duplicate_string(location+": "+type+str+details+get_callstack());
103-
// RPG Hacker: TODO: Rework this into a full call stack return value once we bump the DLL API version again.
104-
myerr.callerline=get_previous_file_line_no();
105-
const char* prev_file = get_previous_file_name();
106-
myerr.callerfilename=prev_file ? duplicate_string(prev_file) : nullptr;
107113
myerr.errname = duplicate_string(errname);
114+
115+
autoarray<printable_callstack_entry> printable_stack;
116+
get_full_printable_callstack(&printable_stack, 0, false);
117+
118+
myerr.callstacksize = printable_stack.count;
119+
myerr.callstack = static_cast<stackentry*>(malloc(sizeof(stackentry) * myerr.callstacksize));
120+
121+
for (int i = 0; i < myerr.callstacksize; ++i)
122+
{
123+
stackentry& entry = const_cast<stackentry&>(myerr.callstack[i]);
124+
125+
entry.fullpath = duplicate_string(printable_stack[i].fullpath);
126+
entry.prettypath = duplicate_string(printable_stack[i].prettypath);
127+
entry.lineno = printable_stack[i].lineno;
128+
entry.details = duplicate_string(printable_stack[i].details);
129+
}
108130
}
109131

110132
static bool ismath=false;
@@ -149,9 +171,17 @@ static void resetdllstuff()
149171
free_and_null(errors[i].filename);
150172
free_and_null(errors[i].rawerrdata);
151173
free_and_null(errors[i].fullerrdata);
152-
free_and_null(errors[i].callerfilename);
153174
free_and_null(errors[i].block);
154175
free_and_null(errors[i].errname);
176+
177+
for (int j=0;j<errors[i].callstacksize;++j)
178+
{
179+
stackentry& entry = const_cast<stackentry&>(errors[i].callstack[j]);
180+
free_and_null(entry.fullpath);
181+
free_and_null(entry.prettypath);
182+
free_and_null(entry.details);
183+
}
184+
free_and_null(errors[i].callstack);
155185
}
156186
errors.reset();
157187
numerror=0;
@@ -161,8 +191,17 @@ static void resetdllstuff()
161191
free_and_null(warnings[i].filename);
162192
free_and_null(warnings[i].rawerrdata);
163193
free_and_null(warnings[i].fullerrdata);
164-
free_and_null(warnings[i].callerfilename);
165194
free_and_null(warnings[i].block);
195+
free_and_null(warnings[i].errname);
196+
197+
for (int j=0;j<warnings[i].callstacksize;++j)
198+
{
199+
stackentry& entry = const_cast<stackentry&>(warnings[i].callstack[j]);
200+
free_and_null(entry.fullpath);
201+
free_and_null(entry.prettypath);
202+
free_and_null(entry.details);
203+
}
204+
free_and_null(warnings[i].callstack);
166205
}
167206
warnings.reset();
168207
numwarn=0;

src/asar/interface-lib.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,21 @@
88
#include <stddef.h> // for size_t
99

1010
//These structures are returned from various functions.
11+
struct stackentry {
12+
const char * fullpath;
13+
const char * prettypath;
14+
int lineno;
15+
const char * details;
16+
};
17+
1118
struct errordata {
1219
const char * fullerrdata;
1320
const char * rawerrdata;
1421
const char * block;
1522
const char * filename;
1623
int line;
17-
const char * callerfilename;
18-
int callerline;
24+
const struct stackentry * callstack;
25+
int callstacksize;
1926
const char * errname;
2027
};
2128

src/asar/main.cpp

Lines changed: 38 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -136,18 +136,23 @@ string generate_call_details_string(const char* current_block, const char* curre
136136
return e;
137137
}
138138

139-
string generate_filename_and_line(const char* current_file, int current_line_no)
139+
string get_pretty_filename(const char* current_file)
140140
{
141141
// RPG Hacker: One could make an argument that we shouldn't shorten paths
142142
// here, since some IDEs support jumping to files by double-clicking their
143143
// paths. However, AFAIK, no IDE supports this for Asar yet, and if it's
144144
// ever desired, we could just make it a command line option. Until then,
145145
// I think it's more important to optimize for pretty command line display.
146-
return STR shorten_to_relative_path(get_top_level_directory(), current_file)
146+
return shorten_to_relative_path(get_top_level_directory(), current_file);
147+
}
148+
149+
string generate_filename_and_line(const char* current_file, int current_line_no)
150+
{
151+
return STR current_file
147152
+ (current_line_no>=0?STR ":"+dec(current_line_no+1):"");
148153
}
149154

150-
void push_stack_line(autoarray<string>* lines, const char* current_file, const char* current_block, const char* current_call, int current_line_no, int stack_frame_index)
155+
string format_stack_line(const printable_callstack_entry& entry, int stack_frame_index)
151156
{
152157
string indent = "\n| ";
153158
indent += dec(stack_frame_index);
@@ -156,10 +161,19 @@ void push_stack_line(autoarray<string>* lines, const char* current_file, const c
156161
// hundreds even, so this very specific, lazy solution suffices.
157162
if (stack_frame_index < 100) indent += " ";
158163
if (stack_frame_index < 10) indent += " ";
159-
lines->append(indent
160-
+ generate_filename_and_line(current_file, current_line_no)
161-
+ generate_call_details_string(current_block, current_call, 12, true)
162-
);
164+
return indent
165+
+ generate_filename_and_line(entry.prettypath, entry.lineno)
166+
+ entry.details;
167+
}
168+
169+
void push_stack_line(autoarray<printable_callstack_entry>* out, const char* current_file, const char* current_block, const char* current_call, int current_line_no, int indentation, bool add_lines)
170+
{
171+
printable_callstack_entry new_entry;
172+
new_entry.fullpath = current_file;
173+
new_entry.prettypath = get_pretty_filename(current_file);
174+
new_entry.lineno = current_line_no;
175+
new_entry.details = strip_whitespace(generate_call_details_string(current_block, current_call, indentation, add_lines).raw());
176+
out->append(new_entry);
163177
}
164178

165179
void get_current_line_details(string* location, string* details, bool exclude_block)
@@ -175,7 +189,7 @@ void get_current_line_details(string* location, string* details, bool exclude_bl
175189
case callstack_entry_type::FILE:
176190
current_file = callstack[i].content;
177191
if (exclude_block) current_block = nullptr;
178-
*location = generate_filename_and_line(current_file, current_line_no);
192+
*location = generate_filename_and_line(get_pretty_filename(current_file), current_line_no);
179193
*details = generate_call_details_string(current_block, current_call, 4, false);
180194
return;
181195
case callstack_entry_type::MACRO_CALL:
@@ -194,9 +208,9 @@ void get_current_line_details(string* location, string* details, bool exclude_bl
194208
*details = "";
195209
}
196210

197-
string get_full_callstack()
211+
void get_full_printable_callstack(autoarray<printable_callstack_entry>* out, int indentation, bool add_lines)
198212
{
199-
autoarray<string> lines;
213+
out->reset();
200214
const char* current_file = nullptr;
201215
const char* current_block = nullptr;
202216
const char* current_call = nullptr;
@@ -208,7 +222,7 @@ string get_full_callstack()
208222
case callstack_entry_type::FILE:
209223
if (current_file != nullptr)
210224
{
211-
push_stack_line(&lines, current_file, current_block, current_call, current_line_no, lines.count);
225+
push_stack_line(out, current_file, current_block, current_call, current_line_no, indentation, add_lines);
212226
}
213227
current_file = callstack[i].content;
214228
current_block = nullptr;
@@ -228,16 +242,21 @@ string get_full_callstack()
228242
break;
229243
}
230244
}
231-
// RPG Hacker: This pop here is incorrect, because with the
232-
// way we traverse the call stack, the highest level is
233-
// already automatically excluded, anyways.
234-
//if (lines.count > 0) lines.remove(lines.count-1);
235-
245+
}
246+
247+
string get_full_callstack()
248+
{
249+
autoarray<printable_callstack_entry> printable_stack;
250+
get_full_printable_callstack(&printable_stack, 12, true);
251+
236252
string e;
237-
if (lines.count > 0)
253+
if (printable_stack.count > 0)
238254
{
239255
e += "\nFull call stack:";
240-
for (int i = lines.count-1; i >= 0; --i) e += lines[i];
256+
for (int i = printable_stack.count-1; i >= 0; --i)
257+
{
258+
e += format_stack_line(printable_stack[i], i);
259+
}
241260
}
242261
return e;
243262
}
@@ -293,7 +312,7 @@ string get_simple_callstack()
293312
string e;
294313
if (current_call != nullptr && current_file != nullptr)
295314
{
296-
e += STR "\n called from: " + generate_filename_and_line(current_file, current_line_no)
315+
e += STR "\n called from: " + generate_filename_and_line(get_pretty_filename(current_file), current_line_no)
297316
+ ": [%" + current_call + "]";
298317
}
299318
return e;
@@ -1156,38 +1175,6 @@ const char* get_current_block()
11561175
return nullptr;
11571176
}
11581177

1159-
const char* get_previous_file_name()
1160-
{
1161-
int num_files = 0;
1162-
for (int i = callstack.count-1; i >= 0; --i)
1163-
{
1164-
if (callstack[i].type == callstack_entry_type::FILE)
1165-
{
1166-
num_files++;
1167-
if (num_files > 1) return callstack[i].content.raw();
1168-
}
1169-
}
1170-
return nullptr;
1171-
}
1172-
1173-
int get_previous_file_line_no()
1174-
{
1175-
int num_files = 0;
1176-
for (int i = callstack.count-1; i >= 0; --i)
1177-
{
1178-
if (callstack[i].type == callstack_entry_type::FILE)
1179-
{
1180-
num_files++;
1181-
if (num_files > 1) return -1;
1182-
}
1183-
else if (callstack[i].type == callstack_entry_type::LINE)
1184-
{
1185-
if (num_files == 1) return callstack[i].lineno;
1186-
}
1187-
}
1188-
return -1;
1189-
}
1190-
11911178

11921179
void reseteverything()
11931180
{

0 commit comments

Comments
 (0)