Well, I made a function parser for my own purposes and I want to share it.
It's coded in python, but you can parse the output with any language (manually or using JSON)... it works like a pre-processor, it does the hard work for you.
You can also insert data directly into a database with python without parsing anything.
The software will read all the files in "includes" directory (relative to him) and will get all the information from each function.
Here is the function structure:
Code:
pos 0: include file
pos 1: function name
pos 2: function modifier
pos 3: return type (not exactly a return type, it only shows if there is Float: or something like that before the function name)
pos 4: all the parameters as they are declared
pos 5: params count number
pos 6: a list with each param
pos 6-0: the whole param as it's declared
pos 6-1: variable type
pos 6-2: variable name
pos 6-3: 1 if the variable is passed by reference, 0 otherwise
pos 6-4: default value (if there is any)
pos 6-5: 1 if the variable is optional, 0 otherwise
Example: ['amxmisc.inc', 'cmd_target', 'stock', '', 'id,constarg[],flags=CMDTARGET_OBEY_IMMUNITY', 3, [['id', 'int', 'id', 0, '', 0], ['constarg[]', 'cell[]', 'constarg', 0, '', 0], ['flags=CMDTARGET_OBEY_IMMUNITY', 'int', 'flags', 0, 'CMDTARGET_OBEY_IMMUNITY', 1]]]
Parser code
PHP Code:
import re;
import json;
from os import listdir;
from os.path import isfile, join;
def getFuncReturnType(line):
line = re.sub(r"\(.*\)", "", line);
if not ":" in line:
return "";
line = re.sub(r".* (.*):.*", r"\1", line);
return line;
def getFuncName(line):
return re.sub(r".*(?::| )(.*)\(.*", r"\1", line);
def getModifier(line):
if re.compile("stock").match(line):
return "stock";
elif re.compile("forward").match(line):
return "forward";
elif re.compile("native").match(line):
return "native";
def getFuncParams(line):
return re.sub(r".*\((.*)\).*", r"\1", line);
def getFuncParamsCount(params):
if params == "":
return 0;
return len(re.split(",(?!_})", params));
def parseParams(params):
if params == "":
return [];
params = re.split(",(?!_})", params);
temp = [];
for i in params:
temp.append(parseParam(i));
return temp;
def parseParam(param):
varType = "cell";
varParam = param;
if re.compile("^const ").match(param):
varType = "const "+varType;
if param[0] == '&':
varRef = 1;
else:
varRef = 0;
if ":" in param:
temp = param.split(':');
varType = temp[0].replace('&','');
param = temp[1];
varDef = param.split('=');
varOptional = 0;
if len(varDef)>1:
varDef = varDef[1];
varOptional = 1;
else:
varDef = "";
varName = re.sub(r"(?:\[[0-9]*(?: char)?\])?(?:=.*)?","", param);
temp = re.sub(r"(?:=.*)?", "", param);
temp = temp.replace(varName, '');
if temp == "":
varType = re.sub(r"^cell", "int", varType);
else:
varType += temp;
varName = varName.replace('&','');
if "any:..." in varParam:
varOptional = 1;
return [varParam, varType, varName, varRef, varDef, varOptional];
regex = re.compile("^(?:stock |native |forward )");
functions = [];
for f in listdir("include"):
if isfile(join("include",f)):
fp = open("include/"+f, "r");
lineas = fp.readlines();
print f;
print "";
for line in lineas:
line = line.replace('\n','').replace('\t','').replace('\r','');
if (regex.match(line) and "stock const" not in line and not "Float:operator" in line and not "bool:operator" in line):
line = re.sub(r"\).*", ")", line);
line = re.sub(r"/\*.*\*/", "", line);
line = line.replace(' ','');
line = re.sub(r"^stock", "stock ", line);
line = re.sub(r"^native", "native ", line);
line = re.sub(r"^forward", "forward ", line);
funcName = getFuncName(line);
funcModifier = getModifier(line);
funcReturnType = getFuncReturnType(line);
funcParams = getFuncParams(line);
funcParamsCount = getFuncParamsCount(funcParams);
funcParamsDetails = parseParams(funcParams);
data = [f, funcName, funcModifier, funcReturnType, funcParams, funcParamsCount, funcParamsDetails];
functions.append(data);
print funcName;
fp.close();
print "";
print "";
print "";
readable = "";
parseable = "";
for i in functions:
readable += str(i)+"\n";
for k in i:
if type(k) == list:
for x in k:
for j in x:
parseable += str(j)+"!;;;!";
if x != []:
parseable = parseable[0:len(parseable)-5];
parseable += "!;;!";
if k != []:
parseable = parseable[0:len(parseable)-4];
parseable += "!;!";
else:
parseable += str(k)+"!;!";
if i != []:
parseable = parseable[0:len(parseable)-3];
parseable += "\n";
fp = open("readable-output.txt", "w");
fp.write(readable);
fp.close();
fp = open("parseable-output.txt", "w");
fp.write(parseable);
fp.close();
fp = open("json-output.txt", "w");
fp.write(json.dumps(functions));
fp.close();
It has 3 outputs. I parsed all amxx-cstrike includes
readable-output.txt - Example:
http://pastebin.com/uSgYykxM
parseable-output.txt - Example:
http://pastebin.com/Q9rMg5ER
json-output.txt - Example:
http://pastebin.com/2DYdRkNJ
Here is a php function to parse "parseable-output.txt"
PHP Code:
function fileToArray($file){
$data = file_get_contents($file);
$functions = preg_split("/\n/", $data);
$fileInArray = Array();
foreach ($functions as $funcData){
$function = preg_split("/!;!/", $funcData);
foreach ($function as $func){
$funcInfo = preg_split("/!;;!/", $func);
if (count($funcInfo)>1 || stristr($funcInfo[0], "!;;;!")){
$temp1 = Array();
foreach ($funcInfo as $paramsInfo){
$paramInfo = preg_split("/!;;;!/", $paramsInfo);
$temp2 = Array();
foreach ($paramInfo as $paramData){
$temp2[] = $paramData;
}
$temp1[] = $temp2;
}
$fileInArray[] = $temp1;
} else {
$fileInArray[] = $funcInfo[0];
}
}
}
return $fileInArray;
}
var_export(fileToArray("parseable-output.txt"));
Output example (it's a valid php array code):
Clic me (I can't upload it to pastebin because it reachs 500kb filezise limitation).
PS: I didn't care about efficience, it could be easily optimizated a lot but I just wanted to code it fast since I will only run it once
__________________