#
# This awk script converts a data file in the format of:
#
#	long _hread(
#	    HFILE  hFile,	// handle of file 
#	    LPVOID  lpBuffer,	// address of buffer for read data 
#	    long  lBytes 	// length, in bytes, of data buffer 
#	   );	
#
# to 
#
#	_hread
#	300
#	%DLG:%DEFR:long$%DEFF:_hread$%DEFPL:($%DEFPS:,$ %DEF:\tHFILE  ......
#



BEGIN {
	TRUE  = 1
	FALSE = 0

	pass1 = 1;
	pass2 = 1;
    cpp   = 0;
	useClassNameFiles = 0;
	txtname      = ""

	dlgIdx = 0;
	dlgStrStack[ 0 ] = "";
	dlgNameStack[ 0 ] = "";

	numFOpen = 0;
	MAX_FILES_OPEN = 10   # stupid to have to limit this

	lineStackIdx  = 0;
	lineStack[ 0 ] = "";
	bLParanFound = FALSE;
	bRParanFound = FALSE;
	classname    = ""

	keywords[ "DECLARE_HANDLE" ] = 0;
	keywords[ "typedef"        ] = 0;
	dbfnames[ "" ] = 0;

}


// { 
	prev_classname = classname;

	if (cpp && match( $0, /[a-zA-z0-9_]+::/ ))
		classname = trim(ltrim(substr( $0, RSTART, RLENGTH - 2)));

	if (pass1)
	{
		bLineAppended = FALSE;

		if (index( $0, "\(" ))
		{
			if (bLParanFound || bRParanFound)
			{
				lineStackIdx = 0;
				bLParanFound = FALSE;
				bRParanFound = FALSE;
			}
			else
			{
				bLParanFound  = TRUE;
				bLineAppended = TRUE;
				lineStack[ lineStackIdx++ ] = $0;
			}
		}
	
	
		if (bLParanFound && index( $0, "\)" ))
		{
			bRParanFound = TRUE;
	
			if (bLineAppended == FALSE)
			{
				bLineAppended = TRUE;
				lineStack[ lineStackIdx++ ] = $0;
			}
		}
	
		if (index( $0, ";" ))
		{
			if (bLParanFound && bRParanFound)
			{
				if (bLineAppended == FALSE)
					lineStack[ lineStackIdx++ ] = $0;
	
				lineStr = "";
				for (i = 0; i < lineStackIdx; i++)
				{
					if (i != 0)
#EJ						lineStr = lineStr " "
						lineStr = lineStr "\n"
					lineStr = lineStr lineStack[ i ];
				}
	
				bKwdFound = FALSE;
				for (kwd in keywords)
				{
					if (index( lineStr, kwd ))
					{
						bKwdFound = TRUE;
						break;
					}
				}
	
				if ((bKwdFound == FALSE) ) #&& (match( lineStr, /\)[ \t]*;/)))
				{
					if (pass2)
						lineStr = parse_line( cpp ? classname : "", lineStr );
					else if (cpp)
						lineStr = classname "::\n" lineStr;

					dlgStrStack[ dlgIdx++ ] = lineStr;
				}
			}
	
			lineStackIdx = 0;
			bLParanFound = FALSE;
			bRParanFound = FALSE;
		}
		else if (bLParanFound && (bLineAppended == FALSE))
		{
			lineStack[ lineStackIdx++ ] = $0;
		}
	}
	else if (pass2 && (!cpp || (prev_classname != "")))
	{
		dlgStrStack[ dlgIdx++ ] = parse_line( cpp ? classname : "", $0 ) 
		classname = "";

	}

}

function parse_line( classname, lineStr ) 
{
	dlgLineStr = "";

	if (match( lineStr, /[ \t]*[a-zA-z0-9_]+[ \t]*\(/ ))
	{
		func_name = (cpp ? (classname "::") : "") trim(ltrim(substr( lineStr, RSTART, RLENGTH - 1)));

		if (cpp && (RSTART == 1))
			ret_type = classname;
		else
			ret_type = trim(ltrim(substr( lineStr, 1, RSTART )));

		#
		# if the name is repeated, assume it has a different parameter list
		# and append a (<n>) after it's lookup name
		#

		spaces = "";
		nth = 1;
		fstr = dlgNameStack[ dlgIdx - nth ];
		sub( "\\.+$", "", fstr);

		while (fstr == func_name)
		{
			spaces = spaces ".";
			nth++;
			fstr = dlgNameStack[ dlgIdx - nth ];
			sub( "\\.+$", "", fstr);
		}
		dlgNameStack[ dlgIdx ] = func_name spaces;


		lineStr = trim(ltrim(substr( lineStr, RSTART + RLENGTH )));

		delete( parms )
		delete( commentstrs )
		i = 0;

		while (TRUE)
		{
			pLength  = 0;
			pLength1 = index( lineStr, "/" );
			pLength2 = index( lineStr, ","  );
			pLength3 = index( lineStr, ")"  );

			if (pLength1 != 0) 
				pLength = pLength1;
			if (pLength2 != 0) 
				if ((pLength == 0) || (pLength > pLength2))
					pLength = pLength2;
			if (pLength3 != 0) 
				if ((pLength == 0) || (pLength > pLength3))
					pLength = pLength3;
			if (pLength == 0)
				break;

			new_parm = trim(ltrim(substr( lineStr, 1, pLength - 1)));
			if (tolower(new_parm) == "void")
				new_parm = "";
			if (new_parm && (new_parm != ""))
				parms[i++] = new_parm;
			lineStr = trim(ltrim(substr( lineStr, pLength )));
			if ((index( lineStr, "," ) == 1) || (index( lineStr, ")" ) == 1))
				lineStr = ltrim(substr( lineStr, 2 ));

			if (new_parm && (new_parm != ""))
				if (index( lineStr, "//" ) == 1)
				{
					ix = index( lineStr, "\n" );
					if (ix <= 0)
						ix = length( lineStr );
					commentstrs[i-1] = substr( lineStr, 1, ix );
				
					lineStr = substr( lineStr, ix );
				}


		}

		##### This code doesn't work because there is no way to use minimal match
		##		while (match( lineStr, /[,\)]/ ))
		##		{
		##			parms[i++] = trim(ltrim(substr( lineStr, RSTART, RLENGTH - 1)));
		##print "PARMS[" i "] = " parms[i-1]
		##			lineStr = trim(ltrim(substr( lineStr, RSTART + RLENGTH )));
		##		}

		# for (i in parms)
		# 	printf( "pars[%d] = %s\n", i, parms[i] );

#			print ret_type
#			print func_name


		apiname = func_name;
		if (cpp && match( apiname, /[a-zA-z0-9_]+::/ ))
		{
			# break out the class name and use it as the .txt file to
			# write to.
			apiname   = trim(ltrim(substr( apiname, RSTART + RLENGTH )));
		}
			
		dlgLineStr = dlgLineStr sprintf("%%DLG:%%DEFR:%s$%%DEFF:%s$%%DEFPL:($%%DEFPS:,$ ", ret_type, apiname );
		if (classname)
			dlgLineStr = dlgLineStr sprintf( "%%DEFC:%s::$", classname );

		for (i in parms)
		{
			if (i != 0)
				dlgLineStr = dlgLineStr sprintf( "%%DEF:\\n" );
			else
				dlgLineStr = dlgLineStr sprintf( "%%DEF:" );

			if (i in commentstrs)
				dlgLineStr = dlgLineStr sprintf( "\\t%s%s\\t%s", 
					trim(ltrim(parms[ i ])), 
					((i+1 in parms) ? "," : ""),
					trim(ltrim(commentstrs[i])) );
			else
				dlgLineStr = dlgLineStr sprintf( "\\t%s%s", 
					trim(ltrim(parms[ i ])), ((i+1 in parms) ? "," : "") );
			if ((i+1 in parms) == FALSE)
				dlgLineStr = dlgLineStr "\n";
			dlgLineStr = dlgLineStr "$";
		}
		dlgLineStr = dlgLineStr " %DEFPR:)$";

		for (i in parms)
		{
			parm_name = parms[i];
			parm_def  = parm_name;
			if (((pos = rindex( parms[i], "\&" )) != 0) ||
					((pos = rindex( parms[i], "=" )) != 0) ||
					((pos = rindex( parms[i], "\*" )) != 0) ||
					((pos = rindex( parms[i], " " )) != 0) ||
					((pos = rindex( parms[i], "\t" ) != 0) ))
				if (substr( parms[i], pos+1 ) != "")
				{
					parm_name = substr( parms[i], pos+1 );
					parm_type = substr( parms[i], 0, pos );
				}

			# Uncomment to avoid using parm_name as default parameter
			# dlgLineStr = dlgLineStr sprintf( "%%DEF%d:\\n%s,eb$", i+1, parm_name );
			dlgLineStr = dlgLineStr sprintf( "%%DEF%d:\\n%s,eb%s$", 
				i+1, parm_type, "," parm_name );
		}

	}

	return dlgLineStr;
}


function trim( line ) {
	sub( "[ \t\n]*$", "", line);
	return line;
}

function ltrim( line ){
	sub( "^[ \t\n]*", "", line );
	return line;
}


function closeAnyTXTFile( lpClass ){
	for (cname in dbfnames)
		if ((lpClass != cname) && (dbfnames[ cname ] != 0))
		{
			close( dbfnames[ cname ] );
			dbfnames[ cname ] = 0;
			numFOpen--;
			return;
		}
}

function openTXTFile( lpClass ){

	if (numFOpen >= MAX_FILES_OPEN)
		closeAnyTXTFile( lpClass );


	if (lpClass in dbfnames)
		dbfnames[ lpClass ] = fopen( lpClass ".txt", "a" );
	else
	{
		dbfnames[ lpClass ] = fopen( lpClass ".txt", "w" );
		printf "" > dbfnames[ classname ]
	}
	numFOpen++;
}


END {
	magic_kwd = ""

	pf = ((txtname == "") ? stdout : fopen( txtname,"w" ) );

	if (pf > 0)
	{
		printf ""  > pf

		# create the file and write to it
		for (i in dlgStrStack )
		{
			apiname = dlgNameStack[ i ];


			if (cpp && pass2 && match( apiname, /[a-zA-z0-9_]+::/ ))
			{
				# break out the class name and use it as the .txt file to
				# write to.

				classname = trim(ltrim(substr( apiname, RSTART, RLENGTH - 2)));
				apiname   = trim(ltrim(substr( apiname, RSTART + RLENGTH )));
	

				if ((classname in dbfnames) && (dbfnames[ classname ] != 0))
					;
				else
				{
					# This is the first time this class was encountered.
					# Open a file if instructed to do so. Also
					# create an encoded keyname entry mapping the classname
					# to a filename
					if (!(classname in dbfnames))
						magic_kwd = classname;

					dbfnames[ classname ] = 0;
					if (useClassNameFiles)
						openTXTFile( classname );
				}

				if (useClassNameFiles)
					pf = dbfnames[ classname ];

				print apiname "\t[" classname "::]" >> pf;
			}
			else
				print apiname >> pf;

			if (pass2)
				print length( dlgStrStack[i] ) >> pf;
			print dlgStrStack[ i ]  >> pf;

			#  if (magic_kwd != "")
			#  {
			#  	print "\1\1\1:" magic_kwd >> pf
			#  	print 0                 >> pf
			#  	print                   >> pf
			#  	magic_kwd = ""
			#  }

		}
	}
	else
		print "Error: unable to open txtfile: " txtname
}

