C++: list structs in a header file

Talk about things C/C++, some related to AutoHotkey
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

C++: list structs in a header file

Post by jeeswg » 13 Apr 2019, 14:12

Here is some provisional code to list the structs in a header file (.h file) via AHK, and to then retrieve their sizes via C++. The list generated is not guaranteed to be 100% complete, but the script has proven quite effective at retrieving struct names. Tested on CommCtrl.h and WinUser.h.

Code: Select all

;AHK v2 script

#Warn
ListLines("Off")

;q:: ;list structs in a header file (.h file) (provisional script)
vPath := "C:\Program Files (x86)\Windows Kits\8.1\Include\um\CommCtrl.h"
;vPath := "C:\Program Files (x86)\Windows Kits\8.1\Include\um\WinUser.h"
if !FileExist(vPath)
{
	MsgBox("error: file not found:`r`n" vPath)
	return
}
vText := FileRead(vPath)
vDoGetNext := 0
vTemp2 := ""
vIndent := ""
VarSetCapacity(vOutput, 1000000*2)
VarSetCapacity(vListDefine, 1000000*2)
oDict := ComObjCreate("Scripting.Dictionary")

;get struct names from 'typedef struct' definitions
;and store potential struct names from '#define' directives
Loop Parse vText, "`n", "`r"
{
	vTemp := LTrim(A_LoopField) ;remove leading spaces/tabs
	vTemp := RegExReplace(vTemp, "[ `t]+", " ")
	vTemp := RegExReplace(vTemp, " //.*")
	if (SubStr(vTemp, 1, 7) = "#define")
	{
		;ignore numeric definitions etc
		if !RegExMatch(vTemp, "[(\\\-:" Chr(34) "]| \d")
			vListDefine .= vTemp "`r`n"
		continue
	}

	vTemp := A_LoopField
	;if (vPos := RegExMatch(vTemp, "typedef"))
	if (vPos := RegExMatch(vTemp, "typedef struct"))
	{
		vTemp2 := vTemp
		vIndent := SubStr(vTemp, 1, vPos-1)
		vDoGetNext := 1
	}
	else if vDoGetNext
	&& (SubStr(vTemp, 1, StrLen(vIndent)+1) = vIndent "}")
	{
		vTemp := RegExReplace(vTemp, "^[} ]+|[,;].*")
		if !(vTemp = "")
		&& !oDict.Exists("" vTemp)
		&& !(vTemp = "DUMMYUNIONNAME")
		{
			oDict.Item["" vTemp] := 1
			vOutput .= vTemp "`r`n"
			;vOutput .= vTemp2 "`t" vTemp "`r`n"
		}
		vDoGetNext := 0
	}
}

;get struct names from stored '#define' directives
;lines of the form '#define newname oldname'
vOutput .= "`r`n"
Loop Parse vListDefine, "`n", "`r"
{
	oTemp := StrSplit(A_LoopField, " ")
	if (oTemp.Length() = 3)
	&& !oDict.Exists("" oTemp.2) ;new name not seen before
	&& oDict.Exists("" oTemp.3) ;old name seen before
	{
		oDict.Item["" oTemp.2] := 1
		vOutput .= oTemp.2 "`r`n"
	}
}

;get raw list of structs:
;Clipboard := RTrim(vOutput, "`r`n") "`r`n"
;MsgBox(vOutput)

vList := vOutput
VarSetCapacity(vOutput, StrLen(vList)*10*2)
Loop Parse vList, "`n", "`r"
{
	vTemp := A_LoopField
	if (vTemp = "")
	{
		vOutput .= "`r`n"
		continue
	}
	vOutput .= "std::cout << " Chr(34) vTemp "=" Chr(34) " << sizeof(" vTemp ") << std::endl;`r`n"
}

Clipboard := RTrim(vOutput, "`r`n") "`r`n"
oDict := ""
MsgBox("done")
return
Example C++ code using code generated by the AHK script.

Code: Select all

//structs get sizes

#include "stdafx.h"
#include <iostream>
#include "Windows.h"
#include "CommCtrl.h"

int _tmain(int argc, _TCHAR* argv[])
{
	std::cout << "TVITEMA=" << sizeof(TVITEMA) << std::endl;
	std::cout << "TVITEMW=" << sizeof(TVITEMW) << std::endl;
	std::cout << "TVITEM=" << sizeof(TVITEM) << std::endl;
	std::getchar();
	return 0;
}
Note: another approach would be to retrieve unique strings from the header file, paste them into Visual Studio, wait for Visual Studio to colour the appropriate words, copy the list to WordPad, save as an rtf file, and parse the raw rtf for coloured words.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “C/C++”