1#
2# Copyright (c) 2008-2010 Lu, Chao-Ming (Tetralet).  All rights reserved.
3#
4# This file is part of LilyTerm.
5#
6# LilyTerm is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# LilyTerm is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with LilyTerm.  If not, see <http://www.gnu.org/licenses/>.
18#
19
20#!/bin/sh
21
22INCLUDES="$1"
23
24RUN_GDB=0
25RUN_VALGRIND=0
26TEST_SCRIPT_ONLY=0
27BUILD_ONLY=0
28LIB_LISTS="lilyterm.h"
29FUNCTION_FOUND=0
30
31ECHO=`whereis "echo" | tr -s ' ' '\n' | grep "bin/""echo""$" | head -n 1`
32PRINTF=`whereis "printf" | tr -s ' ' '\n' | grep "bin/""printf""$" | head -n 1`
33CAT=`whereis "cat" | tr -s ' ' '\n' | grep "bin/""cat""$" | head -n 1`
34GDB=`whereis "gdb" | tr -s ' ' '\n' | grep "bin/""gdb""$" | head -n 1`
35VALGRIND=`whereis "valgrind" | tr -s ' ' '\n' | grep "bin/""valgrind""$" | head -n 1`
36
37MAKE=`whereis "gmake" | tr -s ' ' '\n' | grep "bin/""gmake""$" | head -n 1`
38if [ -z "$MAKE" ]; then
39	MAKE=`whereis "make" | tr -s ' ' '\n' | grep "bin/""make""$" | head -n 1`
40fi
41
42for opt do
43	case "$opt" in
44		--help)
45			$ECHO "Usage: sh $0 INCLUDES --test_all --enable-glib-debugger --enable-gtk-debugger --enable-gdb --enable-valgrind --specific_function=FUNCTION_NAME --skip_function=FUNCTION_NAME --create_program_only --build_program_only"
46			exit 0
47			;;
48		--test_all)
49			LIB_LISTS="*.h"
50			export G_DEBUG=fatal_warnings
51			;;
52		--enable-glib-debugger)
53			export G_DEBUG=fatal_warnings
54			;;
55		--enable-gtk-debugger)
56			GTK_DEBUG="--g-fatal-warnings"
57			;;
58		--enable-gdb)
59			RUN_GDB=1
60			;;
61		--enable-valgrind)
62			RUN_VALGRIND=1
63			;;
64		--specific_function=*)
65			SPECIFIC_FUNCTION=`$ECHO $opt | cut -d '=' -f 2`
66			LIB_LISTS="*.h"
67			;;
68		--skip_function=*)
69			SKIP_FUNCTION=`$ECHO $opt | cut -d '=' -f 2`
70			;;
71		--create_program_only)
72			TEST_SCRIPT_ONLY=1
73			;;
74		--build_program_only)
75			BUILD_ONLY=1
76			;;
77	esac
78done
79
80CHECK_INCLUDES=`$ECHO "$INCLUDES" | grep -- '-DUNIT_TEST'`
81if [ -z "$CHECK_INCLUDES" ]; then
82	if [ -f lilyterm -o -f lilyterm-dbg -o -f lilyterm_dev ]; then
83		$MAKE clean
84	fi
85	$MAKE uto || exit 1
86	INCLUDES="-DSAFEMODE -DDEBUG -DFATAL -DDEVELOP -DUNIT_TEST"
87fi
88
89PKGCONFIG=`whereis "pkg-config" | tr -s ' ' '\n' | grep "bin/""pkg-config""$" | head -n 1`
90if [ -z "$PKGCONFIG" ]; then
91	$PRINTF "\033[1;31m** ERROR: Command pkg-config is not found!\033[0m\n"
92	exit 1
93fi
94
95VTE=`$PKGCONFIG --exists 'vte' && $ECHO 'vte'`
96if [ "$VTE" = "vte" ]; then
97  GTK=`$PKGCONFIG --exists 'gtk+-2.0' && $ECHO 'gtk+-2.0'`
98  if [ "$GTK" != "gtk+-2.0" ]; then
99    $PRINTF "\033[1;31m** ERROR: You need GTK+2 to run this unit test program!\033[0m\n"
100    exit 1
101  fi
102else
103  VTE=`$PKGCONFIG --exists 'vte-2.90' && $ECHO 'vte-2.90'`
104  if [ "$VTE" = "vte-2.90" ]; then
105    GTK=`$PKGCONFIG --exists 'gtk+-3.0' && $ECHO 'gtk+-3.0'`
106    if [ "$GTK" != "gtk+-3.0" ]; then
107      $PRINTF "\033[1;31m** ERROR: You need GTK+3 to run this unit test program!\033[0m\n"
108      exit 1
109    fi
110  else
111    $PRINTF "\033[1;31m** ERROR: You need VTE to run this unit test program!\033[0m\n"
112    exit 1
113  fi
114fi
115
116if [ -z "$CC" ]; then
117  CC=gcc
118fi
119
120if [ -z "$CFLAGS" ]; then
121  CFLAGS="-Wall -Werror -O -g"
122fi
123
124OBJ="menu.o profile.o dialog.o pagename.o notebook.o font.o property.o window.o misc.o console.o main.o unit_test.o"
125
126$CAT > gdb_batch << EOF
127run
128backtrace full
129info registers
130thread apply all backtrace
131quit
132EOF
133
134if [ -f gdb.log ]; then
135	$PRINTF "\n\033[1;36mDeleting gdb.log...\033[0m\n\n"
136	rm -f gdb.log
137fi
138if [ -f valgrind.log ]; then
139	$PRINTF "\n\033[1;36mDeleting valgrind.log...\033[0m\n\n"
140	rm -f valgrind.log
141fi
142
143# sed '/^\/\*/,/ \*\/$/d': Delete [ /* blah ... blah */ ] (multi lines)
144# sed -e 's/[ \t]*\/\*[ \t]*.*[ \t]*\*\///g': Delete [ /* blah ... blah */ ] (single line)
145# sed -e 's/[ \t]*\/\/.*//g': Delete [ // blah ... blah ]
146# sed -e '/[ \t]*#[ \t]*ifdef[ \t]*USE_GTK3_GEOMETRY_METHOD/,/#[ \t]*endif[ \t]*/d': clear #ifdef USE_GTK3_GEOMETRY_METHOD ... #endif
147# sed -e '/^[ \t]*#.*/d' | tr -d '\n': Delete [ #include ]
148# sed '/^[ \t]*typedef enum/,/}.*;[ \t]*$/d': Delete typedef enum
149# tr -d '\n': Delete [ <NewLine> ]
150# sed -e 's/[\t ][\t ]*/_SPACE_/g': convert <Tab> and <Space> to "_SAPCE_"
151# sed -e 's/;/;\n/g': Add [ <NewLine> ] back
152# sed -e 's/_SPACE_/ /g': convert "_SAPCE_" to <Space>
153# sed -e '/[ \t]*struct.*{/,/.*}[ \t]*;/d': clear struct
154# sed -e 's/ *\([)(,]\) */ \1 /g': Add <Space> to the start and end of )(,
155# sed -e 's/[\t ][\t ]*/_SPACE_/g': convert <Tab> and <Space> to "_SAPCE_" again
156# sed -e '/_SPACE_(_SPACE_)_SPACE_/d': clear something like [ blah ( )  ]
157
158for DATA in `$CAT $LIB_LISTS | sed '/^\/\*/,/ \*\/$/d' | sed -e 's/[ \t]*\/\*[ \t]*.*[ \t]*\*\///g' | sed -e 's/[ \t]*\/\/.*//g' | sed -e '/^[ \t]*#.*/d' | sed '/^[ \t]*typedef.*;[ \t]*$/d' | sed '/^[ \t]*typedef enum/,/}.*;[ \t]*$/d' | tr -d '\n' | sed -e 's/[\t ][\t ]*/_SPACE_/g' | sed -e 's/;/;\n/g' | sed -e 's/_SPACE_/ /g' | sed -e '/[ \t]*struct.*{/,/.*}[ \t]*;/d' | sed -e 's/ *\([)(,]\) */ \1 /g' | sed -e 's/[\t ][\t ]*/_SPACE_/g' | sed -e '/_SPACE_(_SPACE_)_SPACE_/d'`; do
159
160	if [ $FUNCTION_FOUND -eq 1 ]; then
161		break
162	fi
163
164	if [ -n "$SKIP_FUNCTION" ]; then
165		CHECK_STR="_SPACE_\**"$SKIP_FUNCTION"_SPACE_"
166		CHECK_PROGRAM=`$ECHO "$DATA" | grep "$CHECK_STR"`
167		if [ -n "$CHECK_PROGRAM" ]; then
168			continue
169		fi
170	fi
171
172	if [ -n "$SPECIFIC_FUNCTION" ]; then
173		CHECK_STR="_SPACE_\**"$SPECIFIC_FUNCTION"_SPACE_"
174		CHECK_PROGRAM=`$ECHO "$DATA" | grep "$CHECK_STR"`
175		if [ -z "$CHECK_PROGRAM" ]; then
176			continue
177		else
178			FUNCTION_FOUND=1
179		fi
180	fi
181	MAX_STR=0
182	MAX_VAR=-1
183	unset FULL_FUNCTION
184
185	# $ECHO "Got original data = $DATA"
186	# sed -e 's/_SPACE_\([)(,]\)_SPACE_/ \1 /g': convert _SPACE_)(,_SPACE_ to " ) " " ( " or " , "
187	# sed -e 's/ , / /g': convert " , " to " "
188	# sed -e 's/const_SPACE_//g': clear const_SPACE_
189	DATA_STR=`$ECHO $DATA | sed -e 's/_SPACE_\([)(,]\)/ \1/g' | sed -e 's/\([)(,]\)_SPACE_/\1 /g' | sed -e 's/ , / /g' | sed -e 's/const_SPACE_//g'`
190	# $ECHO "GOT DATA_STR = $DATA_STR" 1>&2
191	START=0
192	END=0
193	VAR=-1
194
195	for STR in $DATA_STR; do
196		# $ECHO "GOT and Checking STR='$STR'"
197		case $START in
198			0)
199				if [ "$STR" = "(" ]; then
200					START=1
201					FUNCTION="("
202					# $ECHO "GOT FUNCTION = $FUNCTION"
203				else
204					# Got the function name.
205					unset FUNC_STAR
206					unset FUNC_END
207					unset SPACE
208					# sed -e 's/_SPACE_/ /g' : convert "_SAPCE_" to <Space>
209					# sed -e 's/^ *//g': clear the leading <Space>
210					# sed -e 's/ *$//g': clear the end <Space>
211					# sed -e 's/^.* \**\([^ ]*\)/\1/g': clear the declare, like "gchar **"
212					FUNC_NAME=`$ECHO $STR | sed -e 's/_SPACE_/ /g' | sed -e 's/^ *//g' | sed -e 's/ *$//g' | sed -e 's/^.* \**\([^ ]*\)/\1/g'`
213					# $ECHO "GOT FUNC_NAME = $FUNC_NAME"
214					$PRINTF "\033[1;36m$FUNC_NAME(): \033[1;33m** Createing unit_test.c...\033[0m\n"
215				fi
216				;;
217			1)
218				if [ "$STR" = ")" ]; then
219					FUNCTION=`$ECHO $FUNCTION | sed -e 's/,*$/)/g'`
220					START=2
221					continue
222				fi
223				# $ECHO "CHECKING: GOT FUNCTION = $FUNCTION"
224				# $ECHO "Testing $STR..." 1>&2
225
226				# sed -e 's/_SPACE_/ /g': convert "_SAPCE_" to <Space>
227				# sed -e 's/^\(.* \**\) *\([^][ ]*\)\([[]*\)[^][ ]*\([]]*\)/\1\3\4/g': convert "gchar *profile[A]" to gchar *[]
228				# sed -e 's/^ *//g': clear the leading <Space>
229				# sed -e 's/ *$//g': clear the end <Space>
230				# sed -e 's/^.* \**\([^ ]*\)/\1/g': clear the variable
231				STR=`$ECHO $STR | sed -e 's/_SPACE_/ /g' | sed -e 's/^\(.* \**\) *\([^][ ]*\)\([[]*\)[^][ ]*\([]]*\)/\1\3\4/g' | sed -e 's/^ *//g' | sed -e 's/ *$//g' | sed -e 's/ *\*/*/g'`
232				# $ECHO "GOT and Testing \"$STR\"..." 1>&2
233				case $STR in
234					'...')
235						;;
236					'GtkWidget*' | 'GSourceFunc' | 'gpointer' | 'GtkColorSelection*' | 'GtkTreePath*' | 'GtkTreeModel*' | 'GtkTreeIter*' | 'GdkEvent*' | 'GdkEventKey*' | 'GtkCellLayout*' | 'GtkTreeSelection*' | 'GtkClipboard*' | 'GError*' | 'GSList*' | 'GIOChannel*' | 'GtkFileChooser*' | 'GtkRequisition*' | 'GdkEventButton*' | 'GtkStyle*' | 'GtkAllocation*' | 'GdkEventFocus*' | 'GdkEventWindowState*' | 'GdkColor []')
237						FUNCTION="$FUNCTION NULL,"
238						;;
239					'GKeyFile*'|'GdkColor')
240						OLD_SPACE="$SPACE"
241						SPACE="$SPACE""_SPACE_"
242						VAR=`expr $VAR + 1`
243						if [ $MAX_VAR -le $VAR ]; then
244							MAX_VAR=$VAR
245						fi
246						case $STR in
247							'GKeyFile*')
248								FUNC_STAR="$FUNC_STAR\n$SPACE""GKeyFile *V$VAR = g_key_file_new();"
249								FUNCTION="$FUNCTION V$VAR,"
250								FUN_DATA="$SPACE""g_key_file_free(V$VAR);\n"
251								;;
252							'GdkColor')
253								FUNC_STAR="$FUNC_STAR\n$SPACE""GdkColor V$VAR;\n$SPACE""V$VAR.red=0xFFFF;\n$SPACE""V$VAR.green=0xFFFF;\n$SPACE""V$VAR.blue=0xFFFF;"
254								FUNCTION="$FUNCTION V$VAR,"
255								;;
256						esac
257						if [ -n "$FUNC_END" ]; then
258							FUNC_END="\n$FUNC_END"
259						fi
260						FUNC_END="$FUN_DATA$FUNC_END"
261						unset FUN_DATA
262						SPACE=$OLD_SPACE
263						;;
264					'gboolean' | 'gchar' | 'guint' | 'GtkScrollType' | 'gint' | 'pid_t' | 'int' | 'gsize' | 'glong' | 'GdkColor' | 'Dialog_Button_Type' | 'Dialog_Find_Type' | 'Dialog_Type_Flags' | 'Font_Name_Type' | 'Font_Reset_Type' | 'Switch_Type' | 'Font_Set_Type' | 'Set_ANSI_Theme_Type' | 'GtkFileChooserAction' | 'GIOCondition' | 'Check_Zero' | 'Check_Max' | 'Check_Min' | 'Check_Empty' | 'Menu_Itemn_Type' | 'Apply_Profile_Type' | 'Clipboard_Type' | 'gchar*' | 'char*' | 'StrLists*' | 'StrAddr**' | 'gdouble' | 'struct Dialog*' | 'struct Window*' | 'struct Page*' | 'struct Color_Data*' | 'struct Preview*' | 'GtkButton*' | 'GtkCellRenderer*' | 'GtkRange*' | 'gchar**' | 'char*[]' | 'char**' | 'gsize*' | 'GString*' | 'GtkNotebook*' | 'GdkColor*' | 'VteTerminal*'  | 'gboolean*' | 'gint*' | 'guint*')
265						SPACE="$SPACE""_SPACE_"
266						VAR=`expr $VAR + 1`
267						if [ $MAX_VAR -le $VAR ]; then
268							MAX_VAR=$VAR
269						fi
270						case $STR in
271							'gboolean' | 'guint' | 'gint' | 'pid_t' | 'int' | 'gsize' | 'glong' | 'gdouble' | 'gchar')
272								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
273								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""$STR V$VAR = V[$VAR];"
274								FUNCTION="$FUNCTION V$VAR,"
275								;;
276							'gboolean*' | 'gint*' | 'guint*' | 'gsize*')
277								NO_STAR_STR=`$ECHO $STR | sed -e 's/\*$//g'`
278								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
279								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""$NO_STAR_STR V$VAR = V[$VAR];"
280								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""$STR G$VAR = NULL;"
281								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""if (V[$VAR]) G$VAR = ($STR)&(V$VAR);"
282								FUNCTION="$FUNCTION G$VAR,"
283								;;
284							'Dialog_Button_Type' | 'Dialog_Find_Type' | 'Dialog_Type_Flags' | 'Font_Name_Type' | 'Font_Reset_Type' | 'Switch_Type' | 'Font_Set_Type' | 'Set_ANSI_Theme_Type' | 'Check_Zero' | 'Check_Max' | 'Check_Min' | 'Check_Empty' | 'Menu_Itemn_Type' | 'Apply_Profile_Type' | 'Clipboard_Type')
285								LAST=`grep -B 1 "$STR;" *.h | head -n 1 | sed -e 's/^.*[ \t][ \t]*\([^ \t]*\),.*/\1/g'`
286								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<=$LAST; V[$VAR]++) {"
287								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""$STR V$VAR = V[$VAR];"
288								FUNCTION="$FUNCTION V$VAR,"
289								;;
290							'GtkScrollType')
291								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<=GTK_SCROLL_END; V[$VAR]++) {"
292								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""$STR V$VAR = V[$VAR];"
293								FUNCTION="$FUNCTION V$VAR,"
294								;;
295							'GtkFileChooserAction')
296								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<=GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; V[$VAR]++) {"
297								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""$STR V$VAR = V[$VAR];"
298								FUNCTION="$FUNCTION V$VAR,"
299								;;
300							'GIOCondition')
301								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<=G_IO_NVAL; V[$VAR]++) {"
302								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""$STR V$VAR = V[$VAR];"
303								FUNCTION="$FUNCTION V$VAR,"
304								;;
305							'gchar')
306								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
307								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""$STR V$VAR = CHAR[V[$VAR]];"
308								FUNCTION="$FUNCTION V$VAR,"
309								;;
310							'gchar*' | 'char*')
311								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
312								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""gchar *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = g_strdup(\"\");"
313								FUNCTION="$FUNCTION V$VAR,"
314								FUN_DATA="$FUN_DATA$SPACE""_SPACE_""g_free(V$VAR);\n"
315								;;
316							'StrLists*')
317								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
318								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""StrLists *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = g_strdup(\"\");"
319								FUNCTION="$FUNCTION V$VAR, NULL"
320								FUN_DATA="$FUN_DATA$SPACE""_SPACE_""g_free(V$VAR);\n"
321								;;
322							'StrAddr**')
323								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
324								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""StrAddr *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = g_strdup(\"\");"
325								FUNCTION="$FUNCTION &V$VAR,"
326								# FUN_DATA="$SPACE""_SPACE_""g_debug(\"$FUNC_NAME(): Trying to free V$VAR \\\"%s\\\" (%p)\", V$VAR, V$VAR);\n"
327								FUN_DATA="$FUN_DATA$SPACE""_SPACE_""g_free(V$VAR);\n"
328								;;
329							'struct Dialog*' | 'struct Window*' | 'struct Page*' | 'struct Color_Data*' | 'struct Preview*')
330								STRUCT=`$ECHO $STR | sed -e 's/struct \(.*\)\*/\1/g'`
331								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
332								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""struct $STRUCT *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = g_new0(struct $STRUCT, 1);"
333								FUNCTION="$FUNCTION V$VAR,"
334								FUN_DATA="$SPACE""_SPACE_""g_free(V$VAR);\n"
335								;;
336							'GtkButton*')
337								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
338								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""GtkWidget *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = gtk_button_new();"
339								FUNCTION="$FUNCTION GTK_BUTTON(V$VAR),"
340								FUN_DATA="$SPACE""_SPACE_""if (V$VAR) gtk_widget_destroy(V$VAR);\n"
341								;;
342							'GtkCellRenderer*')
343								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
344								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""GtkCellRenderer *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = gtk_cell_renderer_text_new();"
345								FUNCTION="$FUNCTION V$VAR,"
346								# FUN_DATA="$SPACE""_SPACE_""if (V$VAR) gtk_object_destroy(GTK_OBJECT(V$VAR));\n"
347								;;
348							'GtkRange*')
349								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
350								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""GtkWidget *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = gtk_hscale_new_with_range(-1, 1, 0.1);"
351								FUNCTION="$FUNCTION GTK_RANGE(V$VAR),"
352								FUN_DATA="$SPACE""_SPACE_""if (V$VAR) gtk_widget_destroy(V$VAR);\n"
353								;;
354							'gchar**' | 'char*[]' | 'char**')
355								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
356								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""gchar **V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = g_strsplit(\"\", \" \", -1);"
357								FUNCTION="$FUNCTION V$VAR,"
358								FUN_DATA="$SPACE""_SPACE_""g_strfreev(V$VAR);\n"
359								;;
360							'GString*')
361								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
362								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""GString *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = g_string_new(NULL);"
363								FUNCTION="$FUNCTION V$VAR,"
364								FUN_DATA="$SPACE""_SPACE_""if (V$VAR) g_string_free(V$VAR, TRUE);\n"
365								;;
366							'GtkNotebook*')
367								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
368								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""GtkWidget *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = gtk_notebook_new();"
369								FUNCTION="$FUNCTION GTK_NOTEBOOK(V$VAR),"
370								FUN_DATA="$SPACE""_SPACE_""if (V$VAR) gtk_widget_destroy(V$VAR);\n"
371								;;
372							'GdkColor*')
373								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
374								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""GdkColor *V$VAR = NULL;\n$SPACE""_SPACE_""GdkColor color;\n""$SPACE""_SPACE_""if (V[$VAR]) {\n$SPACE""_SPACE__SPACE_""color.red=0xFFFF;\n$SPACE""_SPACE__SPACE_""color.green=0xFFFF;\n$SPACE""_SPACE__SPACE_""color.blue=0xFFFF;\n$SPACE""_SPACE__SPACE_""V$VAR = &color;\n""$SPACE""_SPACE_""}"
375								FUNCTION="$FUNCTION V$VAR,"
376								;;
377							'VteTerminal*')
378								FUNC_STAR="$FUNC_STAR\n$SPACE""for (V[$VAR]=0; V[$VAR]<2; V[$VAR]++) {"
379								FUNC_STAR="$FUNC_STAR\n$SPACE""_SPACE_""GtkWidget *V$VAR = NULL;\n""$SPACE""_SPACE_""if (V[$VAR]) V$VAR = vte_terminal_new();"
380								FUNCTION="$FUNCTION VTE_TERMINAL(V$VAR),"
381								FUN_DATA="$SPACE""_SPACE_""if (V$VAR) gtk_widget_destroy(V$VAR);\n"
382								;;
383							*)
384								$ECHO "ERROR: $STR NOT Found!" 1>&2
385								exit
386								;;
387						esac
388						FUNC_END="$FUN_DATA$SPACE}\n$FUNC_END"
389						unset FUN_DATA
390						# $ECHO "Got FUNC_STAR = $FUNC_STAR"
391						# $ECHO "Got FUNC_END = $FUNC_END" 1>&2
392						;;
393					')')
394						FUNCTION=`$ECHO $FUNCTION | sed -e 's/,$/)/g'`
395						;;
396					*)
397						$ECHO "ERROR: \"$STR\" NOT Found!" 1>&2
398						exit
399						;;
400				esac
401				;;
402			2)
403				case $STR in
404					';')
405						FUNCTION="$FUNCTION;"
406						;;
407					*)
408						$ECHO "ERROR: \"$STR\" NOT Found!" 1>&2
409						exit
410						;;
411				esac
412				;;
413			*)
414				$ECHO "ERROR: \"$START\" is out of range!" 1>&2
415		esac
416	done
417
418	# $ECHO "GOT FULL_FUNCTION = $FULL_FUNCTION" 1>&2
419	# $ECHO "GOT FUNC_STAR = $FUNC_STAR" 1>&2
420	# $ECHO "GOT FUNCTION = $FUNCTION" 1>&2
421	# $ECHO "GOT FUNC_END = $FUNC_END" 1>&2
422	FUNCTION=`$ECHO $FUNCTION | sed -e 's/^( /(/g'`
423	FUNCTION="$SPACE""_SPACE_""$FUNC_NAME$FUNCTION"
424	FULL_FUNCTION="$FULL_FUNCTION\n  g_debug(\"UNIT TEST: testing $FUNC_NAME()...\");"
425	FULL_FUNCTION="$FULL_FUNCTION$FUNC_STAR\n$FUNCTION\n$FUNC_END"
426
427	MAX_VAR=`expr $MAX_VAR + 1`
428
429	grep "include <.*>" *.h | cut -f 2 -d : | sed -e 's/^[ \t]//g' | sort | uniq > unit_test.c
430	for FILE in *.h; do
431		$ECHO "#include \"$FILE\"" >> unit_test.c
432	done
433
434	$CAT >> unit_test.c << EOF
435
436int main(int argc, char *argv[])
437{
438EOF
439	if [ $MAX_VAR -gt 0 ]; then
440		$CAT >> unit_test.c << EOF
441  gint V[$MAX_VAR];
442EOF
443fi
444	$CAT >> unit_test.c << EOF
445  gtk_init(&argc, &argv);
446EOF
447
448	# $ECHO "GOT FULL_FUNCTION = $FULL_FUNCTION"
449	$ECHO "$FULL_FUNCTION" | sed -e 's/\\n/\n/g' | sed -e 's/_SPACE_/  /g' >> unit_test.c
450
451	$CAT >> unit_test.c << EOF
452  return 0;
453}
454EOF
455	if [ $TEST_SCRIPT_ONLY -eq 0 ]; then
456		$PRINTF "\033[1;36m$FUNC_NAME(): \033[1;33m** Compiling unit_test.o...\033[0m\n"
457		$CC $CFLAGS $INCLUDES -c unit_test.c `$PKGCONFIG --cflags $GTK $VTE` || exit 1
458		$PRINTF "\033[1;36m$FUNC_NAME(): \033[1;33m** Compiling unit_test...\033[0m\n"
459		$CC $CFLAGS $INCLUDES -o unit_test $OBJ `$PKGCONFIG --cflags --libs $GTK $VTE` || exit 1
460		# if [ $? != 0 ]; then exit 1; fi
461
462		if [ $BUILD_ONLY -eq 0 ]; then
463			if [ $RUN_GDB -eq 1 ]; then
464				$PRINTF "\033[1;36m$FUNC_NAME(): \033[1;33m** Testing with $GDB...\033[0m\n"
465				if [ -n "$SPECIFIC_FUNCTION" ]; then
466					$GDB -batch -x ./gdb_batch --args ./unit_test $GTK_DEBUG
467				else
468					$ECHO "Testing $FUNC_NAME() with $GDB..." > /tmp/lilyterm_$FUNC_NAME.log
469					$GDB -batch -x ./gdb_batch --args ./unit_test $GTK_DEBUG  >> /tmp/lilyterm_$FUNC_NAME.log 2>&1
470					CHECK_STR=`tail -n 4 /tmp/lilyterm_$FUNC_NAME.log | grep 'exited normally'`
471					if [ -z "$CHECK_STR" ]; then
472						$CAT /tmp/lilyterm_$FUNC_NAME.log >> gdb.log
473						$ECHO "" >> gdb.log
474					else
475						$PRINTF "\033[1;36m$FUNC_NAME(): \033[1;33m** Program exited normally. Clear log...\033[0m\n"
476					fi
477					rm /tmp/lilyterm_$FUNC_NAME.log
478				fi
479			fi
480
481			if [ $RUN_VALGRIND -eq 1 ]; then
482				$PRINTF "\033[1;36m$FUNC_NAME(): \033[1;33m** Testing with valgrind...\033[0m\n"
483				$ECHO "Testing $FUNC_NAME() with $VALGRIND..." >> valgrind.log
484				$VALGRIND --leak-check=full ./unit_test >> valgrind.log 2>&1
485				$ECHO "" >> valgrind.log
486			fi
487		fi
488	fi
489	$ECHO ""
490done
491
492if [ -f ./gdb_batch ]; then
493	rm ./gdb_batch
494fi
495