Subversion Repositories Kolibri OS

Rev

Rev 8975 | Rev 8977 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 8975 Rev 8976
Line 1... Line 1...
1
import re
1
import re
2
import os
2
import os
3
import argparse
3
import argparse
4
import sys
4
import sys
Line 5... Line -...
5
 
-
 
6
""" TODO:
-
 
7
    - Optimize name and var_type checking
-
 
8
"""
-
 
9
 
5
 
10
# Parameters
6
# Parameters
11
# Path to doxygen folder to make doxygen files in: -o 
7
# Path to doxygen folder to make doxygen files in: -o 
12
doxygen_src_path = 'docs/doxygen'
8
doxygen_src_path = 'docs/doxygen'
13
# Remove generated doxygen files: --clean
9
# Remove generated doxygen files: --clean
Line 1152... Line 1148...
1152
	"dq", "rq",
1148
	"dq", "rq",
1153
	"dt", "rt",
1149
	"dt", "rt",
1154
	"du",
1150
	"du",
1155
]
1151
]
Line -... Line 1152...
-
 
1152
 
-
 
1153
# Dict where an identifier is assicoated with a string
-
 
1154
# The string contains characters specifying flags
-
 
1155
# Available flags:
-
 
1156
#  k - Keyword
-
 
1157
#  m - Macro name
-
 
1158
#  t - fasm data Type name (db, rq, etc.)
-
 
1159
#  s - Struct type name
-
 
1160
#  e - equated constant (name equ value)
-
 
1161
#  = - set constants (name = value)
-
 
1162
ID_KIND_KEYWORD = 'k'
-
 
1163
ID_KIND_MACRO_NAME = 'm'
-
 
1164
ID_KIND_FASM_TYPE = 't'
-
 
1165
ID_KIND_STRUCT_NAME = 's'
-
 
1166
ID_KIND_EQUATED_CONSTANT = 'e'
-
 
1167
ID_KIND_SET_CONSTANT = '='
-
 
1168
id2kind = {}
-
 
1169
 
-
 
1170
# Add kind flag to identifier in id2kind
-
 
1171
def id_add_kind(identifier, kind):
-
 
1172
	if identifier not in id2kind:
-
 
1173
		id2kind[identifier] = ''
-
 
1174
	id2kind[identifier] += kind
-
 
1175
 
-
 
1176
# Remove kind flag of identifier in id2kind
-
 
1177
def id_remove_kind(identifier, kind):
-
 
1178
	if identifier in id2kind:
-
 
1179
		if kind in id2kind[identifier]:
-
 
1180
			id2kind[identifier] = id2kind[identifier].replace(kind, '')
-
 
1181
 
-
 
1182
# Get kind of an identifier
-
 
1183
def id_get_kind(identifier):
-
 
1184
	if identifier in id2kind:
-
 
1185
		return id2kind[identifier]
-
 
1186
	else:
-
 
1187
		return ''
-
 
1188
 
-
 
1189
for keyword in keywords:
-
 
1190
	id_add_kind(keyword, ID_KIND_KEYWORD)
-
 
1191
 
-
 
1192
for fasm_type in fasm_types:
-
 
1193
	id_add_kind(fasm_type, ID_KIND_FASM_TYPE)
1156
 
1194
 
1157
# Warning list
1195
# Warning list
Line 1158... Line 1196...
1158
warnings = ""
1196
warnings = ""
1159
 
1197
 
1160
# Parse arguments
1198
# Parse arguments
1161
parser = argparse.ArgumentParser()
1199
parser = argparse.ArgumentParser()
1162
parser.add_argument("-o", help="Doxygen output folder")
1200
parser.add_argument("-o", help="Doxygen output folder")
1163
parser.add_argument("--clean", help="Remove generated files", action="store_true")
1201
parser.add_argument("--clean", help="Remove generated files", action="store_true")
1164
parser.add_argument("--dump", help="Dump all defined symbols", action="store_true")
1202
parser.add_argument("--dump", help="Dump all defined symbols", action="store_true")
-
 
1203
parser.add_argument("--stats", help="Print symbol stats", action="store_true")
1165
parser.add_argument("--stats", help="Print symbol stats", action="store_true")
1204
parser.add_argument("--nowarn", help="Do not write warnings file", action="store_true")
1166
parser.add_argument("--nowarn", help="Do not write warnings file", action="store_true")
1205
parser.add_argument("--noemit", help="Do not emit doxygen files (for testing)", action="store_true")
1167
args = parser.parse_args()
1206
args = parser.parse_args()
1168
doxygen_src_path = args.o if args.o else 'docs/doxygen'
1207
doxygen_src_path = args.o if args.o else 'docs/doxygen'
1169
clean_generated_stuff = args.clean
1208
clean_generated_stuff = args.clean
1170
dump_symbols = args.dump
1209
dump_symbols = args.dump
-
 
1210
print_stats = args.stats
Line 1171... Line 1211...
1171
print_stats = args.stats
1211
enable_warnings = not args.nowarn
1172
enable_warnings = not args.nowarn
1212
noemit = args.noemit
1173
 
-
 
1174
# Variables, functions, labels, macros, structure types
-
 
1175
elements = []
-
 
1176
# Names of macroses
-
 
1177
macro_names = []
-
 
1178
# Names of structs
-
 
1179
struct_names = []
-
 
1180
# Equated constant names (name = value)
-
 
Line 1181... Line 1213...
1181
equated_constant_names = []
1213
 
1182
# Literally equated constant names (name equ value)
1214
# Variables, functions, labels, macros, structure types
1183
equ_names = []
1215
elements = []
1184
 
1216
 
Line 1619... Line 1651...
1619
	if len(name) == 0:
1651
	if len(name) == 0:
1620
		return None
1652
		return None
1621
	# If it starts from digit or othervice illegally it's illegal
1653
	# If it starts from digit or othervice illegally it's illegal
1622
	if not is_starts_as_id(name):
1654
	if not is_starts_as_id(name):
1623
		return None
1655
		return None
-
 
1656
	# Get kind of the identifier from id2kind table
-
 
1657
	kind = id_get_kind(name)
1624
	# If it's a keyword, that's not a variable declaration
1658
	# If it's a keyword, that's not a variable declaration
1625
	if name in keywords:
1659
	if ID_KIND_KEYWORD in kind:
1626
		return None
1660
		return None
1627
	# If it's a macro name, that's not a variable declaration
1661
	# If it's a macro name, that's not a variable declaration
1628
	if name in macro_names:
1662
	if ID_KIND_MACRO_NAME in kind:
1629
		return VariableNameIsMacroName(name)
1663
		return VariableNameIsMacroName(name)
1630
	# If it's a datatype or a structure name that's not a variable declaration: that's just a data
1664
	# If it's a datatype or a structure name that's not a variable declaration: that's just a data
1631
	# don't document just a data for now
1665
	# don't document just a data for now
1632
	if name in struct_names or name in fasm_types:
1666
	if ID_KIND_STRUCT_NAME in kind or ID_KIND_FASM_TYPE in kind:
1633
		return None
1667
		return None
1634
	# Skip spaces before type name
1668
	# Skip spaces before type name
1635
	r.skip_spaces()
1669
	r.skip_spaces()
1636
	# Read type name
1670
	# Read type name
1637
	var_type = ""
1671
	var_type = ""
Line 1644... Line 1678...
1644
		# return it
1678
		# return it
1645
		return name
1679
		return name
1646
	# If it starts from digit or othervice illegally it's illegal
1680
	# If it starts from digit or othervice illegally it's illegal
1647
	if not is_starts_as_id(var_type):
1681
	if not is_starts_as_id(var_type):
1648
		return None
1682
		return None
-
 
1683
	# Get kind of type identifier
-
 
1684
	type_kind = id_get_kind(var_type)
1649
	# If it's a keyword, that's not a variable declaration
1685
	# If it's a keyword, that's not a variable declaration
1650
	# return the two words of the lexical structure
1686
	# return the two words of the lexical structure
1651
	if var_type in keywords:
1687
	if ID_KIND_KEYWORD in type_kind:
1652
		return (name, var_type)
1688
		return (name, var_type)
1653
	# Skip spaces before the value
1689
	# Skip spaces before the value
1654
	r.skip_spaces()
1690
	r.skip_spaces()
1655
	# Read the value until the comment or end of the line
1691
	# Read the value until the comment or end of the line
1656
	value = ""
1692
	value = ""
Line 1781... Line 1817...
1781
			first_word += r.step()
1817
			first_word += r.step()
1782
		# Match macro declaration
1818
		# Match macro declaration
1783
		if first_word == "macro":
1819
		if first_word == "macro":
1784
			macro = parse_after_macro(r)
1820
			macro = parse_after_macro(r)
1785
			elements.append(macro)
1821
			elements.append(macro)
1786
			macro_names.append(macro.name)
1822
			id_add_kind(macro.name, ID_KIND_MACRO_NAME)
1787
		# Match structure declaration
1823
		# Match structure declaration
1788
		elif first_word == "struct":
1824
		elif first_word == "struct":
1789
			struct = parse_after_struct(r)
1825
			struct = parse_after_struct(r)
1790
			elements.append(struct)
1826
			elements.append(struct)
1791
			struct_names.append(struct.name)
1827
			id_add_kind(struct.name, ID_KIND_STRUCT_NAME)
1792
		# Match function definition
1828
		# Match function definition
1793
		elif first_word == "proc":
1829
		elif first_word == "proc":
1794
			proc = parse_after_proc(r)
1830
			proc = parse_after_proc(r)
1795
			elements.append(proc)
1831
			elements.append(proc)
1796
		elif first_word == 'format':
1832
		elif first_word == 'format':
Line 1813... Line 1849...
1813
				name = ''
1849
				name = ''
1814
				while is_id(r.curr()):
1850
				while is_id(r.curr()):
1815
					name += r.step()
1851
					name += r.step()
1816
				# Remove the purged macro from the macro names list
1852
				# Remove the purged macro from the macro names list
1817
				try:
1853
				try:
1818
					macro_names.remove(name)
1854
					id_remove_kind(name, ID_KIND_MACRO_NAME)
1819
				except:
1855
				except:
1820
					pass
1856
					pass
1821
				# Skip spaces after the name
1857
				# Skip spaces after the name
1822
				r.skip_spaces()
1858
				r.skip_spaces()
1823
				# If it's comma (',') after then that's not the last purged macro, continue purging
1859
				# If it's comma (',') after then that's not the last purged macro, continue purging
Line 1849... Line 1885...
1849
					comment = r.comment
1885
					comment = r.comment
1850
					# Only handle non-local labels
1886
					# Only handle non-local labels
1851
					if name[0] != '.' and name != "@@" and name != "$Revision":
1887
					if name[0] != '.' and name != "@@" and name != "$Revision":
1852
						elements.append(AsmLabel(r.location(), name, comment))
1888
						elements.append(AsmLabel(r.location(), name, comment))
1853
				elif r.curr() == '=':
1889
				elif r.curr() == '=':
1854
					# Add the equated constant (name = value) to equated constants list
1890
					# Save the identifier as a set constant
1855
					equated_constant_names.append(first_word)
1891
					id_add_kind(first_word, ID_KIND_SET_CONSTANT)
1856
			elif type(var) == tuple:
1892
			elif type(var) == tuple:
1857
				(word_one, word_two) = var
1893
				(word_one, word_two) = var
1858
				if word_two == 'equ':
1894
				if word_two == 'equ':
1859
					# Add the name to equ names list
1895
					# Save the identifier as an equated constant
1860
					equ_names.append(word_one)
1896
					id_add_kind(word_one, ID_KIND_EQUATED_CONSTANT)
1861
		r.nextline()
1897
		r.nextline()
Line 1862... Line 1898...
1862
 
1898
 
1863
def it_neds_to_be_parsed(source_file):
1899
def it_neds_to_be_parsed(source_file):
1864
	dest = doxygen_src_path + '/' + source_file
1900
	dest = doxygen_src_path + '/' + source_file
Line 1927... Line 1963...
1927
		doxygen_file = f"{doxygen_src_path}/{file}"
1963
		doxygen_file = f"{doxygen_src_path}/{file}"
1928
		if (os.path.isfile(doxygen_file)):
1964
		if (os.path.isfile(doxygen_file)):
1929
			print(f"Removing {file}... ", end = '')
1965
			print(f"Removing {file}... ", end = '')
1930
			os.remove(doxygen_file)
1966
			os.remove(doxygen_file)
1931
			print("Done.")
1967
			print("Done.")
1932
else:
1968
elif not noemit:
1933
	print(f"Writing doumented sources to {doxygen_src_path}")
1969
	print(f"Writing doumented sources to {doxygen_src_path}")
Line 1934... Line 1970...
1934
 
1970
 
1935
	i = 0
1971
	i = 0
1936
	for element in elements:
1972
	for element in elements: