summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/luaprofiler
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luaprofiler')
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/Makefile19
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/clocks.c63
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/clocks.h20
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.c180
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.h31
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.c203
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.h64
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/lua50_profiler.c230
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/luaprofiler.h14
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/stack.c33
-rw-r--r--Build/source/texk/web2c/luatexdir/luaprofiler/stack.h44
11 files changed, 901 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/Makefile b/Build/source/texk/web2c/luatexdir/luaprofiler/Makefile
new file mode 100644
index 00000000000..57ccbfd165f
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/Makefile
@@ -0,0 +1,19 @@
+
+srcdir=../../../src/libs/luaprofiler
+
+OBJS= clocks.o \
+ core_profiler.o \
+ function_meter.o \
+ stack.o \
+ lua50_profiler.o
+
+
+profiler: $(OBJS)
+ ar cru libprofiler.a $(OBJS)
+ ranlib libprofiler.a
+
+clean:
+ rm -f $(OBJS) libprofiler.a
+
+%.o: $(srcdir)/%.c
+ $(CC) -c -I../../../src/libs/lua51 $< $(CFLAGS) -o $@
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.c b/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.c
new file mode 100644
index 00000000000..e693c48535f
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.c
@@ -0,0 +1,63 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: clocks.c,v 1.4 2007/08/22 19:23:53 carregal Exp $
+*/
+
+/*****************************************************************************
+clocks.c:
+ Module to register the time (seconds) between two events
+
+Design:
+ 'lprofC_start_timer()' marks the first event
+ 'lprofC_get_seconds()' gives you the seconds elapsed since the timer
+ was started
+*****************************************************************************/
+
+#include <stdio.h>
+#include "clocks.h"
+
+/*
+ Here you can choose what time function you are going to use.
+ These two defines ('TIMES' and 'CLOCK') correspond to the usage of
+ functions times() and clock() respectively.
+ Which one is better? It depends on your needs:
+ TIMES - returns the clock ticks since the system was up
+ (you may use it if you want to measure a system
+ delay for a task, like time spent to get input from keyboard)
+ CLOCK - returns the clock ticks dedicated to the program
+ (this should be prefered in a multithread system and is
+ the default choice)
+
+ note: I guess TIMES don't work for win32
+*/
+
+#ifdef TIMES
+
+ #include <sys/times.h>
+
+ static struct tms t;
+
+ #define times(t) times(t)
+
+#else /* ifdef CLOCK */
+
+ #define times(t) clock()
+
+#endif
+
+
+void lprofC_start_timer(clock_t *time_marker) {
+ *time_marker = times(&t);
+}
+
+static clock_t get_clocks(clock_t time_marker) {
+ return times(&t) - time_marker;
+}
+
+float lprofC_get_seconds(clock_t time_marker) {
+clock_t clocks;
+ clocks = get_clocks(time_marker);
+ return (float)clocks / (float)CLOCKS_PER_SEC;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.h b/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.h
new file mode 100644
index 00000000000..b2c7fd7d4d5
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/clocks.h
@@ -0,0 +1,20 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: clocks.h,v 1.4 2007/08/22 19:23:53 carregal Exp $
+*/
+
+/*****************************************************************************
+clocks.h:
+ Module to register the time (seconds) between two events
+
+Design:
+ 'lprofC_start_timer()' marks the first event
+ 'lprofC_get_seconds()' gives you the seconds elapsed since the timer
+ was started
+*****************************************************************************/
+
+#include <time.h>
+
+void lprofC_start_timer(clock_t *time_marker);
+float lprofC_get_seconds(clock_t time_marker);
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.c b/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.c
new file mode 100644
index 00000000000..0f70fba106e
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.c
@@ -0,0 +1,180 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005.2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: core_profiler.c,v 1.9 2008/05/19 18:36:23 mascarenhas Exp $
+*/
+
+/*****************************************************************************
+core_profiler.c:
+ Lua version independent profiler interface.
+ Responsible for handling the "enter function" and "leave function" events
+ and for writing the log file.
+
+Design (using the Lua callhook mechanism) :
+ 'lprofP_init_core_profiler' set up the profile service
+ 'lprofP_callhookIN' called whenever Lua enters a function
+ 'lprofP_callhookOUT' called whenever Lua leaves a function
+*****************************************************************************/
+
+/*****************************************************************************
+ The profiled program can be viewed as a graph with the following properties:
+directed, multigraph, cyclic and connected. The log file generated by a
+profiler section corresponds to a path on this graph.
+ There are several graphs for which this path fits on. Some times it is
+easier to consider this path as being generated by a simpler graph without
+properties like cyclic and multigraph.
+ The profiler log file can be viewed as a "reversed" depth-first search
+(with the depth-first search number for each vertex) vertex listing of a graph
+with the following properties: simple, acyclic, directed and connected, for
+which each vertex appears as many times as needed to strip the cycles and
+each vertex has an indegree of 1.
+ "reversed" depth-first search means that instead of being "printed" before
+visiting the vertex's descendents (as done in a normal depth-first search),
+the vertex is "printed" only after all his descendents have been processed (in
+a depth-first search recursive algorithm).
+*****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "function_meter.h"
+
+#include "core_profiler.h"
+
+ /* default log name (%s is used to place a random string) */
+#define OUT_FILENAME "lprof_%s.out"
+
+ /* for faster execution (??) */
+static FILE *outf;
+static lprofS_STACK_RECORD *info;
+static float function_call_time;
+
+
+/* output a line to the log file, using 'printf()' syntax */
+/* assume the timer is off */
+static void output(const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(outf, format, ap);
+ va_end(ap);
+
+ /* write now to avoid delays when the timer is on */
+ fflush(outf);
+}
+
+
+/* do not allow a string with '\n' and '|' (log file format reserved chars) */
+/* - replace them by ' ' */
+static void formats(char *s) {
+ int i;
+ if (!s)
+ return;
+ for (i = strlen(s); i>=0; i--) {
+ if ((s[i] == '|') || (s[i] == '\n'))
+ s[i] = ' ';
+ }
+}
+
+
+/* computes new stack and new timer */
+void lprofP_callhookIN(lprofP_STATE* S, char *func_name, char *file, int linedefined, int currentline) {
+ S->stack_level++;
+ lprofM_enter_function(S, file, func_name, linedefined, currentline);
+}
+
+
+/* pauses all timers to write a log line and computes the new stack */
+/* returns if there is another function in the stack */
+int lprofP_callhookOUT(lprofP_STATE* S) {
+
+ if (S->stack_level == 0) {
+ return 0;
+ }
+
+ S->stack_level--;
+
+ /* 0: do not resume the parent function's timer yet... */
+ info = lprofM_leave_function(S, 0);
+ /* writing a log may take too long to be computed with the function's time ...*/
+ lprofM_pause_total_time(S);
+ info->local_time += function_call_time;
+ info->total_time += function_call_time;
+ formats(info->file_defined);
+ formats(info->function_name);
+ output("%d\t%s\t%s\t%d\t%d\t%f\t%f\n", S->stack_level, info->file_defined,
+ info->function_name,
+ info->line_defined, info->current_line,
+ info->local_time, info->total_time);
+ /* ... now it's ok to resume the timer */
+ if (S->stack_level != 0) {
+ lprofM_resume_function(S);
+ }
+
+ return 1;
+
+}
+
+
+/* opens the log file */
+/* returns true if the file could be opened */
+lprofP_STATE* lprofP_init_core_profiler(const char *_out_filename, int isto_printheader, float _function_call_time) {
+ lprofP_STATE* S;
+ char auxs[256];
+ char *s;
+ char *randstr;
+ const char *out_filename;
+
+ function_call_time = _function_call_time;
+ out_filename = (_out_filename) ? (_out_filename):(OUT_FILENAME);
+
+ /* the random string to build the logname is extracted */
+ /* from 'tmpnam()' (the '/tmp/' part is deleted) */
+ randstr = tmpnam(NULL);
+ for (s = strtok(randstr, "/\\"); s; s = strtok(NULL, "/\\")) {
+ randstr = s;
+ }
+
+ if(randstr[strlen(randstr)-1]=='.')
+ randstr[strlen(randstr)-1]='\0';
+
+ sprintf(auxs, out_filename, randstr);
+ outf = fopen(auxs, "a");
+ if (!outf) {
+ return 0;
+ }
+
+ if (isto_printheader) {
+ output("stack_level\tfile_defined\tfunction_name\tline_defined\tcurrent_line\tlocal_time\ttotal_time\n");
+ }
+
+ /* initialize the 'function_meter' */
+ S = lprofM_init();
+ if(!S) {
+ fclose(outf);
+ return 0;
+ }
+
+ return S;
+}
+
+void lprofP_close_core_profiler(lprofP_STATE* S) {
+ if(outf) fclose(outf);
+ if(S) free(S);
+}
+
+lprofP_STATE* lprofP_create_profiler(float _function_call_time) {
+ lprofP_STATE* S;
+
+ function_call_time = _function_call_time;
+
+ /* initialize the 'function_meter' */
+ S = lprofM_init();
+ if(!S) {
+ return 0;
+ }
+
+ return S;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.h b/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.h
new file mode 100644
index 00000000000..d066ef3d08b
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/core_profiler.h
@@ -0,0 +1,31 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: core_profiler.h,v 1.6 2007/08/22 19:23:53 carregal Exp $
+*/
+
+/*****************************************************************************
+core_profiler.h:
+ Lua version independent profiler interface.
+ Responsible for handling the "enter function" and "leave function" events
+ and for writing the log file.
+
+Design (using the Lua callhook mechanism) :
+ 'lprofP_init_core_profiler' set up the profile service
+ 'lprofP_callhookIN' called whenever Lua enters a function
+ 'lprofP_callhookOUT' called whenever Lua leaves a function
+*****************************************************************************/
+
+#include "stack.h"
+
+/* computes new stack and new timer */
+void lprofP_callhookIN(lprofP_STATE* S, char *func_name, char *file, int linedefined, int currentline);
+
+/* pauses all timers to write a log line and computes the new stack */
+/* returns if there is another function in the stack */
+int lprofP_callhookOUT(lprofP_STATE* S);
+
+/* opens the log file */
+/* returns true if the file could be opened */
+lprofP_STATE* lprofP_init_core_profiler(const char *_out_filename, int isto_printheader, float _function_call_time);
+
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.c b/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.c
new file mode 100644
index 00000000000..2636ee16028
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.c
@@ -0,0 +1,203 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: function_meter.c,v 1.9 2008/05/19 18:36:23 mascarenhas Exp $
+*/
+
+/*****************************************************************************
+function_meter.c:
+ Module to compute the times for functions (local times and total times)
+
+Design:
+ 'lprofM_init' set up the function times meter service
+ 'lprofM_enter_function' called when the function stack increases one level
+ 'lprofM_leave_function' called when the function stack decreases one level
+
+ 'lprofM_resume_function' called when the profiler is returning from a time
+ consuming task
+ 'lprofM_resume_total_time' idem
+ 'lprofM_resume_local_time' called when a child function returns the execution
+ to it's caller (current function)
+ 'lprofM_pause_function' called when the profiler need to do things that
+ may take too long (writing a log, for example)
+ 'lprofM_pause_total_time' idem
+ 'lprofM_pause_local_time' called when the current function has called
+ another one or when the function terminates
+*****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "clocks.h"
+
+/* #include "stack.h" is done by function_meter.h */
+#include "function_meter.h"
+
+#ifdef DEBUG
+#include <stdlib.h>
+#define ASSERT(e, msg) if (!e) { \
+ fprintf(stdout, \
+ "function_meter.c: assertion failed: %s\n", \
+ msg); \
+ exit(1); }
+#else
+#define ASSERT(e, msg)
+#endif
+
+/* structures to receive stack elements, declared globals */
+/* in the hope they will perform faster */
+static lprofS_STACK_RECORD newf; /* used in 'enter_function' */
+static lprofS_STACK_RECORD leave_ret; /* used in 'leave_function' */
+
+
+
+/* sum the seconds based on the time marker */
+static void compute_local_time(lprofS_STACK_RECORD *e) {
+ ASSERT(e, "local time null");
+ e->local_time += lprofC_get_seconds(e->time_marker_function_local_time);
+}
+
+
+/* sum the seconds based on the time marker */
+static void compute_total_time(lprofS_STACK_RECORD *e) {
+ ASSERT(e, "total time null");
+ e->total_time += lprofC_get_seconds(e->time_marker_function_total_time);
+}
+
+
+/* compute the local time for the current function */
+void lprofM_pause_local_time(lprofP_STATE* S) {
+ compute_local_time(S->stack_top);
+}
+
+
+/* pause the total timer for all the functions that are in the stack */
+void lprofM_pause_total_time(lprofP_STATE* S) {
+ lprofS_STACK aux;
+
+ ASSERT(S->stack_top, "pause_total_time: stack_top null");
+
+ /* auxiliary stack */
+ aux = S->stack_top;
+
+ /* pause */
+ while (aux) {
+ compute_total_time(aux);
+ aux = aux->next;
+ }
+}
+
+
+/* pause the local and total timers for all functions in the stack */
+void lprofM_pause_function(lprofP_STATE* S) {
+
+ ASSERT(S->stack_top, "pause_function: stack_top null");
+
+ lprofM_pause_local_time(S);
+ lprofM_pause_total_time(S);
+}
+
+
+/* resume the local timer for the current function */
+void lprofM_resume_local_time(lprofP_STATE* S) {
+
+ ASSERT(S->stack_top, "resume_local_time: stack_top null");
+
+ /* the function is in the top of the stack */
+ lprofC_start_timer(&(S->stack_top->time_marker_function_local_time));
+}
+
+
+/* resume the total timer for all the functions in the stack */
+void lprofM_resume_total_time(lprofP_STATE* S) {
+ lprofS_STACK aux;
+
+ ASSERT(S->stack_top, "resume_total_time: stack_top null");
+
+ /* auxiliary stack */
+ aux = S->stack_top;
+
+ /* resume */
+ while (aux) {
+ lprofC_start_timer(&(aux->time_marker_function_total_time));
+ aux = aux->next;
+ }
+}
+
+
+/* resume the local and total timers for all functions in the stack */
+void lprofM_resume_function(lprofP_STATE* S) {
+
+ ASSERT(S->stack_top, "resume_function: stack_top null");
+
+ lprofM_resume_local_time(S);
+ lprofM_resume_total_time(S);
+}
+
+
+/* the local time for the parent function is paused */
+/* and the local and total time markers are started */
+void lprofM_enter_function(lprofP_STATE* S, char *file_defined, char *fcn_name, long linedefined, long currentline) {
+ char* prev_name;
+ char* cur_name;
+ /* the flow has changed to another function: */
+ /* pause the parent's function timer timer */
+ if (S->stack_top) {
+ lprofM_pause_local_time(S);
+ prev_name = S->stack_top->function_name;
+ } else prev_name = "top level";
+ /* measure new function */
+ lprofC_start_timer(&(newf.time_marker_function_local_time));
+ lprofC_start_timer(&(newf.time_marker_function_total_time));
+ newf.file_defined = file_defined;
+ if(fcn_name != NULL) {
+ newf.function_name = fcn_name;
+ } else if(strcmp(file_defined, "=[C]") == 0) {
+ cur_name = (char*)malloc(sizeof(char)*(strlen("called from ")+strlen(prev_name)+1));
+ sprintf(cur_name, "called from %s", prev_name);
+ newf.function_name = cur_name;
+ } else {
+ cur_name = (char*)malloc(sizeof(char)*(strlen(file_defined)+12));
+ sprintf(cur_name, "%s:%li", file_defined, linedefined);
+ newf.function_name = cur_name;
+ }
+ newf.line_defined = linedefined;
+ newf.current_line = currentline;
+ newf.local_time = 0.0;
+ newf.total_time = 0.0;
+ lprofS_push(&(S->stack_top), newf);
+}
+
+
+/* computes times and remove the top of the stack */
+/* 'isto_resume' specifies if the parent function's timer */
+/* should be restarted automatically. If it's false, */
+/* 'resume_local_time()' must be called when the resume */
+/* should be done */
+/* returns the funcinfo structure */
+/* warning: use it before another call to this function, */
+/* because the funcinfo will be overwritten */
+lprofS_STACK_RECORD *lprofM_leave_function(lprofP_STATE* S, int isto_resume) {
+
+ ASSERT(S->stack_top, "leave_function: stack_top null");
+
+ leave_ret = lprofS_pop(&(S->stack_top));
+ compute_local_time(&leave_ret);
+ compute_total_time(&leave_ret);
+ /* resume the timer for the parent function ? */
+ if (isto_resume)
+ lprofM_resume_local_time(S);
+ return &leave_ret;
+}
+
+
+/* init stack */
+lprofP_STATE* lprofM_init() {
+ lprofP_STATE *S;
+ S = (lprofP_STATE*)malloc(sizeof(lprofP_STATE));
+ if(S) {
+ S->stack_level = 0;
+ S->stack_top = NULL;
+ return S;
+ } else return NULL;
+}
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.h b/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.h
new file mode 100644
index 00000000000..d2eb5a7ca71
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/function_meter.h
@@ -0,0 +1,64 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: function_meter.h,v 1.5 2007/08/22 19:23:53 carregal Exp $
+*/
+
+/*****************************************************************************
+function_meter.c:
+ Module to compute the times for functions (local times and total times)
+
+Design:
+ 'lprofM_init' set up the function times meter service
+ 'lprofM_enter_function' called when the function stack increases one level
+ 'lprofM_leave_function' called when the function stack decreases one level
+
+ 'lprofM_resume_function' called when the profiler is returning from a time
+ consuming task
+ 'lprofM_resume_total_time' idem
+ 'lprofM_resume_local_time' called when a child function returns the execution
+ to it's caller (current function)
+ 'lprofM_pause_function' called when the profiler need to do things that
+ may take too long (writing a log, for example)
+ 'lprofM_pause_total_time' idem
+ 'lprofM_pause_local_time' called when the current function has called
+ another one or when the function terminates
+*****************************************************************************/
+
+#include "stack.h"
+
+
+/* compute the local time for the current function */
+void lprofM_pause_local_time(lprofP_STATE* S);
+
+/* pause the total timer for all the functions that are in the stack */
+void lprofM_pause_total_time(lprofP_STATE* S);
+
+/* pause the local and total timers for all functions in the stack */
+void lprofM_pause_function(lprofP_STATE* S);
+
+/* resume the local timer for the current function */
+void lprofM_resume_local_time(lprofP_STATE* S);
+
+/* resume the total timer for all the functions in the stack */
+void lprofM_resume_total_time(lprofP_STATE* S);
+
+/* resume the local and total timers for all functions in the stack */
+void lprofM_resume_function(lprofP_STATE* S);
+
+/* the local time for the parent function is paused */
+/* and the local and total time markers are started */
+void lprofM_enter_function(lprofP_STATE* S, char *file_defined, char *fcn_name, long linedefined, long currentline);
+
+/* computes times and remove the top of the stack */
+/* 'isto_resume' specifies if the parent function's timer */
+/* should be restarted automatically. If it's false, */
+/* 'resume_local_time()' must be called when the resume */
+/* should be done */
+/* returns the funcinfo structure */
+/* warning: use it before another call to this function, */
+/* because the funcinfo will be overwritten */
+lprofS_STACK_RECORD *lprofM_leave_function(lprofP_STATE* S, int isto_resume);
+
+/* init stack */
+lprofP_STATE* lprofM_init();
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/lua50_profiler.c b/Build/source/texk/web2c/luatexdir/luaprofiler/lua50_profiler.c
new file mode 100644
index 00000000000..54533425c3b
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/lua50_profiler.c
@@ -0,0 +1,230 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: lua50_profiler.c,v 1.13 2008/05/19 18:36:23 mascarenhas Exp $
+*/
+
+/*****************************************************************************
+lua50_profiler.c:
+ Lua version dependent profiler interface
+*****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "clocks.h"
+#include "core_profiler.h"
+#include "function_meter.h"
+
+#include "lua.h"
+#include "lauxlib.h"
+
+/* Indices for the main profiler stack and for the original exit function */
+static int exit_id;
+static int profstate_id;
+
+/* Forward declaration */
+static float calcCallTime(lua_State *L);
+
+/* called by Lua (via the callhook mechanism) */
+static void callhook(lua_State *L, lua_Debug *ar) {
+ int currentline;
+ lua_Debug previous_ar;
+ lprofP_STATE* S;
+ lua_pushlightuserdata(L, &profstate_id);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ S = (lprofP_STATE*)lua_touserdata(L, -1);
+
+ if (lua_getstack(L, 1, &previous_ar) == 0) {
+ currentline = -1;
+ } else {
+ lua_getinfo(L, "l", &previous_ar);
+ currentline = previous_ar.currentline;
+ }
+
+ lua_getinfo(L, "nS", ar);
+
+ if (!ar->event) {
+ /* entering a function */
+ lprofP_callhookIN(S, (char *)ar->name,
+ (char *)ar->source, ar->linedefined,
+ currentline);
+ }
+ else { /* ar->event == "return" */
+ lprofP_callhookOUT(S);
+ }
+}
+
+
+/* Lua function to exit politely the profiler */
+/* redefines the lua exit() function to not break the log file integrity */
+/* The log file is assumed to be valid if the last entry has a stack level */
+/* of 1 (meaning that the function 'main' has been exited) */
+static void exit_profiler(lua_State *L) {
+ lprofP_STATE* S;
+ lua_pushlightuserdata(L, &profstate_id);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ S = (lprofP_STATE*)lua_touserdata(L, -1);
+ /* leave all functions under execution */
+ while (lprofP_callhookOUT(S)) ;
+ /* call the original Lua 'exit' function */
+ lua_pushlightuserdata(L, &exit_id);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_call(L, 0, 0);
+}
+
+/* Our new coroutine.create function */
+/* Creates a new profile state for the coroutine */
+#if 0
+static int coroutine_create(lua_State *L) {
+ lprofP_STATE* S;
+ lua_State *NL = lua_newthread(L);
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
+ "Lua function expected");
+ lua_pushvalue(L, 1); /* move function to top */
+ lua_xmove(L, NL, 1); /* move function from L to NL */
+ /* Inits profiler and sets profiler hook for this coroutine */
+ S = lprofM_init();
+ lua_pushlightuserdata(L, NL);
+ lua_pushlightuserdata(L, S);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ lua_sethook(NL, (lua_Hook)callhook, LUA_MASKCALL | LUA_MASKRET, 0);
+ return 1;
+}
+#endif
+
+static int profiler_pause(lua_State *L) {
+ lprofP_STATE* S;
+ lua_pushlightuserdata(L, &profstate_id);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ S = (lprofP_STATE*)lua_touserdata(L, -1);
+ lprofM_pause_function(S);
+ return 0;
+}
+
+static int profiler_resume(lua_State *L) {
+ lprofP_STATE* S;
+ lua_pushlightuserdata(L, &profstate_id);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ S = (lprofP_STATE*)lua_touserdata(L, -1);
+ lprofM_pause_function(S);
+ return 0;
+}
+
+static int profiler_init(lua_State *L) {
+ lprofP_STATE* S;
+ const char* outfile;
+ float function_call_time;
+
+ function_call_time = calcCallTime(L);
+
+ outfile = NULL;
+ if(lua_gettop(L) == 1)
+ outfile = luaL_checkstring(L, -1);
+
+ lua_sethook(L, (lua_Hook)callhook, LUA_MASKCALL | LUA_MASKRET, 0);
+ /* init with default file name and printing a header line */
+ if (!(S=lprofP_init_core_profiler(outfile, 1, function_call_time))) {
+ luaL_error(L,"LuaProfiler error: output file could not be opened!");
+ lua_pushnil(L);
+ return 1;
+ }
+
+ lua_pushlightuserdata(L, &profstate_id);
+ lua_pushlightuserdata(L, S);
+ lua_settable(L, LUA_REGISTRYINDEX);
+
+ /* use our own exit function instead */
+ lua_getglobal(L, "os");
+ lua_pushlightuserdata(L, &exit_id);
+ lua_pushstring(L, "exit");
+ lua_gettable(L, -3);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ lua_pushstring(L, "exit");
+ lua_pushcfunction(L, (lua_CFunction)exit_profiler);
+ lua_settable(L, -3);
+
+#if 0
+ /* use our own coroutine.create function instead */
+ lua_getglobal(L, "coroutine");
+ lua_pushstring(L, "create");
+ lua_pushcfunction(L, (lua_CFunction)coroutine_create);
+ lua_settable(L, -3);
+#endif
+
+ /* the following statement is to simulate how the execution stack is */
+ /* supposed to be by the time the profiler is activated when loaded */
+ /* as a library. */
+
+ lprofP_callhookIN(S, "profiler_init", "(C)", -1, -1);
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+static int profiler_stop(lua_State *L) {
+ lprofP_STATE* S;
+ lua_sethook(L, (lua_Hook)callhook, 0, 0);
+ lua_pushlightuserdata(L, &profstate_id);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ if(!lua_isnil(L, -1)) {
+ S = (lprofP_STATE*)lua_touserdata(L, -1);
+ /* leave all functions under execution */
+ while (lprofP_callhookOUT(S));
+ lprofP_close_core_profiler(S);
+ lua_pushboolean(L, 1);
+ } else { lua_pushboolean(L, 0); }
+ return 1;
+}
+
+/* calculates the approximate time Lua takes to call a function */
+static float calcCallTime(lua_State *L) {
+ clock_t timer;
+ char lua_code[] = " \
+ function lprofT_mesure_function() \
+ local i \
+ \
+ local t = function() \
+ end \
+ \
+ i = 1 \
+ while (i < 100000) do \
+ t() \
+ i = i + 1 \
+ end \
+ end \
+ \
+ lprofT_mesure_function() \
+ lprofT_mesure_function = nil \
+ ";
+
+ lprofC_start_timer(&timer);
+ luaL_dostring(L, lua_code);
+ return lprofC_get_seconds(timer) / (float) 100000;
+}
+
+static const luaL_reg prof_funcs[] = {
+ { "pause", profiler_pause },
+ { "resume", profiler_resume },
+ { "start", profiler_init },
+ { "stop", profiler_stop },
+ { NULL, NULL }
+};
+
+int luaopen_profiler(lua_State *L) {
+ luaL_openlib(L, "profiler", prof_funcs, 0);
+ lua_pushliteral (L, "_COPYRIGHT");
+ lua_pushliteral (L, "Copyright (C) 2003-2007 Kepler Project");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_DESCRIPTION");
+ lua_pushliteral (L, "LuaProfiler is a time profiler designed to help finding bottlenecks in your Lua program.");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_NAME");
+ lua_pushliteral (L, "LuaProfiler");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_VERSION");
+ lua_pushliteral (L, "2.0.1");
+ lua_settable (L, -3);
+ return 1;
+}
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/luaprofiler.h b/Build/source/texk/web2c/luatexdir/luaprofiler/luaprofiler.h
new file mode 100644
index 00000000000..155f7996fef
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/luaprofiler.h
@@ -0,0 +1,14 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: luaprofiler.h,v 1.4 2007/08/22 19:23:53 carregal Exp $
+*/
+
+/*****************************************************************************
+luaprofiler.h:
+ Must be included by your main module, in order to profile Lua programs
+*****************************************************************************/
+
+
+void init_profiler(void *);
+
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/stack.c b/Build/source/texk/web2c/luatexdir/luaprofiler/stack.c
new file mode 100644
index 00000000000..07754ad95b1
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/stack.c
@@ -0,0 +1,33 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: stack.c,v 1.4 2007/08/22 19:23:53 carregal Exp $
+*/
+
+/*****************************************************************************
+stack.c:
+ Simple stack manipulation
+*****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "stack.h"
+
+void lprofS_push(lprofS_STACK *p, lprofS_STACK_RECORD r) {
+lprofS_STACK q;
+ q=(lprofS_STACK)malloc(sizeof(lprofS_STACK_RECORD));
+ *q=r;
+ q->next=*p;
+ *p=q;
+}
+
+lprofS_STACK_RECORD lprofS_pop(lprofS_STACK *p) {
+lprofS_STACK_RECORD r;
+lprofS_STACK q;
+
+ r=**p;
+ q=*p;
+ *p=(*p)->next;
+ free(q);
+ return r;
+}
diff --git a/Build/source/texk/web2c/luatexdir/luaprofiler/stack.h b/Build/source/texk/web2c/luatexdir/luaprofiler/stack.h
new file mode 100644
index 00000000000..ac27aaa2907
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luaprofiler/stack.h
@@ -0,0 +1,44 @@
+/*
+** LuaProfiler
+** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
+** $Id: stack.h,v 1.5 2007/08/22 19:23:53 carregal Exp $
+*/
+
+/*****************************************************************************
+stack.h:
+ Simple stack manipulation
+*****************************************************************************/
+
+#ifndef _STACK_H
+#define _STACK_H
+
+#include <time.h>
+
+typedef struct lprofS_sSTACK_RECORD lprofS_STACK_RECORD;
+
+struct lprofS_sSTACK_RECORD {
+ clock_t time_marker_function_local_time;
+ clock_t time_marker_function_total_time;
+ char *file_defined;
+ char *function_name;
+ char *source_code;
+ long line_defined;
+ long current_line;
+ float local_time;
+ float total_time;
+ lprofS_STACK_RECORD *next;
+};
+
+typedef lprofS_STACK_RECORD *lprofS_STACK;
+
+typedef struct lprofP_sSTATE lprofP_STATE;
+
+struct lprofP_sSTATE {
+ int stack_level;
+ lprofS_STACK stack_top;
+};
+
+void lprofS_push(lprofS_STACK *p, lprofS_STACK_RECORD r);
+lprofS_STACK_RECORD lprofS_pop(lprofS_STACK *p);
+
+#endif