qrsc_to_tw.py 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199
  1. #!/usr/bin/env python3
  2. import fileinput
  3. import io, os, re, datetime
  4. import hashlib
  5. import variables
  6. verbose = False
  7. #verbose = True
  8. skipMode = 0
  9. #skipMode = -1
  10. verbose_i = 20
  11. error_counter = 1
  12. regex_parts = {}
  13. regex_parts['operator_assign'] = r'=|\+=|-='
  14. regex_parts['parameter'] = r"\$ARGS\[\d+\]"
  15. regex_parts['var'] = r"\$?[a-z]+\w*"
  16. regex_parts['functioncall'] = r"\w+\s*\(\s*\w+\s*(?:,\s*\w*\s*)*\)"
  17. regex_parts['integer'] = r"\d+"
  18. regex_parts['string'] = r"""'\w'|"""+ r'''"\w"'''
  19. regex_parts['value_literal'] = "|".join([regex_parts['integer'],regex_parts['string']])
  20. regex_parts['value'] = "|".join([regex_parts['parameter'],regex_parts['var'],regex_parts['functioncall'],regex_parts['value_literal'] ])
  21. regex_parts['statement'] = '?'
  22. regex_parts['assignment'] = f"\s*({regex_parts['var']})\s*({regex_parts['operator_assign']})\s*({regex_parts['value']})\s*"
  23. def pv(desc,line):
  24. if(verbose):
  25. print(desc.ljust(verbose_i, ' ')+line)
  26. def convert_calculation(right):
  27. pv("START CALCULATION:",right)
  28. brackets_regex = r"""(?<![a-zA-Z0-9])\(\s*([^\)^\(]+(\s*\-|mod|\+|/|\*\s*)[^\)^\(]+)\s*\)"""
  29. #brackets_regex = r"""(?<![a-zA-Z0-9])(?:min|rand|max|mid)\(\s*([^\)^\(]+(\s*\-|mod|\+|/|\*\s*)[^\)^\(]+)\s*\)"""
  30. calculations = []
  31. #print(right)
  32. while b_match := re.search(brackets_regex,right):
  33. complete_match = b_match.group(0)
  34. calculation_raw = b_match.group(1)
  35. operator = b_match.group(2)
  36. if operator == 'mod':
  37. calculation_raw = calculation_raw.replace('mod','%')
  38. calculation = convert_literal(calculation_raw)
  39. index = f"$CALC_HELPER_{len(calculations)}"
  40. right = right.replace(complete_match,index)
  41. calculations.append(calculation)
  42. right = convert_literal(right)
  43. #function_name_regex = r"""(?<![a-zA-Z0-9])(min|rand|mid|max)\s*\$LIT_HELPER_(0)"""
  44. #while function_name_match := re.search(function_name_regex,right):
  45. # complete_match = function_name_match.group(0)
  46. # index = f"$LIT_HELPER_{len(calculations)}"
  47. # right = right.replace(complete_match,index)
  48. # calculations.append(complete_match)
  49. while len(calculations) > 0:
  50. calculation = calculations.pop()
  51. index = f"$CALC_HELPER_{len(calculations)}"
  52. right = right.replace(index,f"({calculation})")
  53. pv("IS CALCULATION:",right)
  54. return right
  55. def convert_command(command_raw):
  56. command = command_raw.strip()
  57. #if (command.startswith('<') or and command.endswith('>'):
  58. # return command
  59. split_by_and = command.split(' & ')
  60. if len(split_by_and) > 1:
  61. return ' '.join([convert_command(s) for s in split_by_and])
  62. assign_operators = ['=','-=','+=']
  63. for assign_operator in assign_operators:
  64. split_by_assign = command.split(assign_operator,1)
  65. if len(split_by_assign) > 1:
  66. left = split_by_assign[0]
  67. if left.startswith('set '):
  68. left = left[4:]
  69. right = split_by_assign[1]
  70. right = convert_calculation(right)
  71. pv("IS ASSIGNMENT:",right)
  72. return f'<<set {convert_literal(left)} {assign_operator} {right}>>'
  73. if match := re.match(r"^(?:set\s*)?(\$?\w+)\s*(\+=|-=|=)\s*([\$']?\w*'?|\w+\s*\(\s*\w+\s*(?:,\s*\w*\s*)*\))$",command):
  74. return f'<<set {convert_literal(match.group(1))} {match.group(2)} {convert_literal(match.group(3))}>>'
  75. if match := re.match(r"""^(x?gt|gs)([\s'"].+)$""",command):
  76. arguments = match.group(2)
  77. pv('GS OR GT:',command)
  78. i = 0
  79. replaces = []
  80. while brackets_match := re.search(r"""\(([^\(^\)]*?,[^\(^\)]*?)\)""",arguments):
  81. original = brackets_match.group(1)
  82. pv("REPLACE:",original)
  83. indentifier = f'$BRACKET_HELER_{i}'
  84. arguments = arguments.replace(original,indentifier)
  85. replaces.append(original)
  86. i += 1
  87. arguments = " ".join([convert_literal(l) for l in arguments.split(',')])
  88. while len(replaces) > 0:
  89. original = replaces.pop()
  90. indentifier = f'$BRACKET_HELER_{len(replaces)}'
  91. arguments = arguments.replace(indentifier,original)
  92. return f'<<{match.group(1)} {arguments}>>'
  93. if match := re.match(r"""^msg\s*(.+)$""",command,re.I):
  94. return f"<<msg {match.group(1)}>>"
  95. if match := re.match(r"""^dynamic \$(.*)$""",command,re.I):
  96. arguments = match.group(1).replace(',',' ')
  97. return f"<<{arguments}>>"
  98. pv("NO COMMAND MATCH:",command)
  99. return ''
  100. def convert_condition(condition_raw):
  101. condition = condition_raw.strip()
  102. if(re.match(r"dyneval\(",condition)):
  103. return condition
  104. #condition = convert_calculation(condition)
  105. #print(condition)
  106. subconditions = []
  107. bracket_search_regex = r"""(?<![a-zA-Z0-9])\(\s*([^\)^\(]+)\s*\)"""
  108. bracket_search_regex = r"""(?<![a-zA-Z0-9])\(\s*([^\)^\(]+(\s*and|or|xor\s*)[^\)^\(]+)\s*\)"""
  109. while match := re.search(bracket_search_regex,condition):
  110. fullmatch = match.group(0)
  111. subcondition = match.group(1)
  112. subcondition_converted = convert_condition(subcondition)
  113. subcondition_ident = f"$CON_HELPER_{len(subconditions)} == 1"
  114. condition = condition.replace(fullmatch,subcondition_ident)
  115. subconditions.append(subcondition_converted)
  116. #print(condition)
  117. if len(subconditions) > 0:
  118. condition = convert_condition(condition)
  119. while len(subconditions) > 0:
  120. subcondition = subconditions.pop()
  121. subcondition_ident = f"$CON_HELPER_{len(subconditions)} == 1"
  122. condition = condition.replace(subcondition_ident,f"({subcondition})")
  123. #print(condition)
  124. return condition
  125. split_by_or = condition.split(' or ')
  126. if len(split_by_or) > 1:
  127. return ' or '.join([convert_condition(s) for s in split_by_or])
  128. split_by_xor = condition.split(' xor ')
  129. if len(split_by_xor) > 1:
  130. return ' xor '.join([convert_condition(s) for s in split_by_xor])
  131. split_by_and = condition.split(' and ')
  132. if len(split_by_and) > 1:
  133. return ' and '.join([convert_condition(s) for s in split_by_and])
  134. #match = re.match(r"(\$ARGS\[\d+\]|\$?\w+)\s*([=><]+)\s*('?\w+'?)",condition)
  135. #match = re.match(r"(\S+)\s*([=><]+)\s*(\S+)",condition)
  136. if(len(condition) >= 2 and condition[0] == '(' and condition[-1] == ')'):
  137. condition = condition[1:-1]
  138. #print(condition)
  139. match = re.match(r"([^<^>^=^!]+)\s*([=><!]+)\s*([^<^>^=^!]+)",condition)
  140. if match:
  141. left = convert_literal(convert_calculation(match.group(1)))
  142. right = convert_literal(match.group(3))
  143. operator = match.group(2)
  144. if operator == '=':
  145. operator = '=='
  146. elif operator == '!':
  147. operator = '!='
  148. elif operator == '=>':
  149. operator = '>='
  150. elif operator == '=<':
  151. operator = '<='
  152. return ' '.join([left,operator,right])
  153. return f'ERROR: FAILED TO CONVERT CONDITION: {condition}'
  154. def convert_literal(literal_raw):
  155. literal = literal_raw.strip()
  156. pv("START LITERAL:",literal)
  157. if not literal:
  158. return ''
  159. subliterals = []
  160. bracket_search_regex = r"""\[\s*([^\]^\[]+)\s*\]"""
  161. while match := re.search(bracket_search_regex,literal):
  162. fullmatch = match.group(0)
  163. subcondition = match.group(1)
  164. subcondition_converted = convert_literal(subcondition)
  165. subcondition_ident = f"LIT_HELPER_{len(subliterals)}"
  166. literal = literal.replace(fullmatch,subcondition_ident)
  167. subliterals.append(subcondition_converted)
  168. #print(condition)
  169. if len(subliterals) > 0:
  170. literal = convert_literal(literal)
  171. while len(subliterals) > 0:
  172. subcondition = subliterals.pop()
  173. subcondition_ident = f"LIT_HELPER_{len(subliterals)}"
  174. literal = literal.replace(subcondition_ident,f"[{subcondition}]")
  175. #print(condition)
  176. return literal
  177. #brackets_regex = r"""\(\s*([^\)^\(]+)\s*\)"""
  178. #function_name_regex = r"""(?<![a-zA-Z0-9])(min|rand|mid|max)\s*\$LIT_HELPER_(0)"""
  179. #calculations = []
  180. #while b_match := re.search(brackets_regex,literal):
  181. # complete_match = b_match.group(0)
  182. # calculation_raw = b_match.group(1)
  183. # calculation_parts = calculation_raw.split(',')
  184. # calculation = ','.join([convert_literal(s) for s in calculation_parts])
  185. # index = f"$LIT_HELPER_{len(calculations)}"
  186. # literal = literal.replace(complete_match,index)
  187. # calculations.append(calculation)
  188. #while function_name_match := re.search(function_name_regex,literal):
  189. # complete_match = function_name_match.group(0)
  190. # index = f"$LIT_HELPER_{len(calculations)}"
  191. # literal = literal.replace(complete_match,index)
  192. # calculations.append(complete_match)
  193. #if len(calculations) > 0:
  194. # literal = convert_literal(literal)
  195. # while len(calculations) > 0:
  196. # calculation = calculations.pop()
  197. # index = f"$LIT_HELPER_{len(calculations)}"
  198. # literal = literal.replace(index,f"({calculation})")
  199. # pv("LITERAL AFTER BRACKETS:",literal)
  200. if(re.match(r"dyneval\(",literal)):
  201. return literal
  202. if literal == "''" or literal == '""':
  203. return literal
  204. if(literal.isnumeric() or (literal.startswith('-') and literal[1:].isnumeric())):
  205. pv("IS NUMERIC",literal)
  206. return literal
  207. if(literal.startswith('(') and len(literal) > 1):
  208. return '('+literal[1:]
  209. if(literal.endswith(')') and len(literal) > 1):
  210. return literal[:-1]+')'
  211. #array_braces = False
  212. #while match:=re.match(r"\$?([a-z][a-z0-9\-_{}'\+]*)(\['(.*?<<.*?>>'*?)'\])",literal,re.I):
  213. # value = match.group(3)
  214. # if not value.startswith("<"):
  215. # value = value.replace("<<","'+")
  216. # else:
  217. # value = value.replace("<<","")#
  218. #
  219. # if not value.endswith(">"):
  220. # value = value.replace(">>","+'")
  221. # else:
  222. # value = value.replace(">>","")
  223. # literal = literal.replace(match.group(2),r"{{"+value+r"}}")
  224. # array_braces = True
  225. #if array_braces:
  226. # literal = literal.replace(r'{{','[').replace(r'}}',']')
  227. if(len(literal)>= 3 and ((literal[0] == '\'' and literal[-1] == '\'') or (literal[0] == '"' and literal[-1] == '"') )):
  228. literal = literal.replace('<<','')
  229. literal = literal.replace('>>','')
  230. literal = literal.replace("''","'")
  231. return literal
  232. if(match := re.match(r"^arrsize\(\s*'(\$?)([a-z]+\w*)'\s*\)$",literal)):
  233. return f"${match.group(2)}.length"
  234. if(match := re.match(r"^killvar\s+'(\$?)([a-z]+\w*)'$",literal,re.I)):
  235. return f"<<set ${match.group(2)} to null>>"
  236. if(match := re.match(r'^\$ARGS\[(\d+)\]$',literal,re.I)):
  237. #ARGS
  238. return f'$location_var[$here][{match.group(1)}]'
  239. if(match := re.match(r'^\$ARGS(LIT_HELPER_\d+)$',literal,re.I)):
  240. #ARGS
  241. return f'$location_var[$here]'+match.group(1)
  242. if(match := re.match(r"^(\$?)[a-zA-z]+\w*(\[('\w*'|\d+)\])?$",literal)):
  243. if match.group(1):
  244. return literal
  245. return '$'+literal
  246. if(match := re.match(r"^(\$?)([a-zA-z]+\w*)\[(.+)\]$",literal)):
  247. #if match.group(1):
  248. # return f"${match.group(2)}[{convert_literal(match.group(3))}]"
  249. return f"${match.group(2)}[{convert_literal(match.group(3))}]"
  250. #print(literal)
  251. if(match := re.match(r'^(\w+)\s*\((\s*\w+\s*(?:,\s*\w*\s*)*)\)$',literal)):
  252. function_name = match.group(1)
  253. function_parameters = match.group(2)
  254. return f'{function_name}({convert_literal(function_parameters)})'
  255. while(match := re.search(r'<<(\$\w+)>>',literal)):
  256. literal = literal.replace(match.group(0),match.group(1))
  257. #Arithmetic Operations
  258. arith_operations = ['*','/','-','+','%',',','mod']
  259. for arith_operation in arith_operations:
  260. split_by_arith = literal.split(arith_operation)
  261. if len(split_by_arith) > 1:
  262. if arith_operation == 'mod':
  263. arith_operation = '%'
  264. return f' {arith_operation} '.join([convert_literal(s) for s in split_by_arith])
  265. if literal.startswith('wait '):
  266. return f'<<{literal}>>'
  267. if(match := re.match(r"""^killvar\s+['"]\$?(.*)['"]$""",literal)):
  268. return f'<<set ${match.group(1)} = 0>>'
  269. if literal.startswith('jump '):
  270. jump_san = literal.replace('"','').replace("'","")
  271. return f"<<warn 'JUMP COMMAND ENCOUNTERED: {jump_san}'>>"
  272. if literal.startswith(':'):
  273. return f"<<warn 'JUMP MARKER ENCOUNTERED: {literal}'>>"
  274. if literal == "'" or literal == '"':
  275. return ''
  276. if re.match(r"""^['"\w\s\?\.!\(\)\$]+$""",literal):
  277. pv("Plain String",literal)
  278. return literal
  279. #return literal
  280. return f'ERROR: FAILED TO CONVERT LITERAL: """{literal}"""'
  281. function_name_conversions = []
  282. def convert_lineblock(lines,location_identifier=''):
  283. outputs = []
  284. nesting = []
  285. commenting = False
  286. isfunction = False
  287. functionlines = []
  288. functionlines_temp = []
  289. function_name = ''
  290. subpassages = {}
  291. subpassage = ''
  292. for line_raw in lines:
  293. #line_raw = lines[line_num]
  294. line = line_raw.strip()
  295. original = line
  296. pv("START:",line)
  297. if len(line) == 0:
  298. continue
  299. whitespace_count = len(nesting)
  300. # Subpassages
  301. if len(subpassage) > 0:
  302. if line.startswith('~$'):
  303. endSubpassageName = line[2:]
  304. gtOrGs = 'gt'
  305. if endSubpassageName.startswith('gs:'):
  306. gtOrGs = 'gs'
  307. endSubpassageName = endSubpassageName[3:]
  308. if endSubpassageName == subpassage:
  309. outputs.append( whitespace_count * '\t' + f"<<{gtOrGs} '{subpassage}' $location_var[$here][0] $location_var[$here][1] $location_var[$here][2] $location_var[$here][3] $location_var[$here][4]>>\n")
  310. subpassage = ''
  311. continue
  312. subpassages[subpassage].append(line)
  313. continue
  314. if len(subpassage) == 0:
  315. if line.startswith('~^'):
  316. startSubpassageName = line[2:]
  317. subpassage = startSubpassageName
  318. subpassages[subpassage] = []
  319. continue
  320. for preparation in preparations:
  321. if len(preparation) > 2:
  322. line = re.sub(preparation[0],preparation[1],line,0,preparation[2])
  323. else:
  324. line = re.sub(preparation[0],preparation[1],line)
  325. line_output = ''
  326. purges = [
  327. 'CLOSE ALL',
  328. 'close all',
  329. '*clr & cla',
  330. 'killall',
  331. 'showstat 0','showstat 1',
  332. 'showobjs 0','showobjs 1',
  333. 'showinput 0','showinput 1'
  334. ]
  335. for purge in purges:
  336. line = line.replace(purge,'')
  337. pv("AFTER PURGES:",line)
  338. #line = line.replace(" mod "," % ")
  339. #while match := re.match(r"iif\s*\((.+),(.*),(.*)\)",line):
  340. # line = line.replace(match.group(0),f"({convert_condition(match.group(1))}) ? {convert_literal(match.group(2))} : {convert_literal(match.group(3))}")
  341. # FUNCTIONS
  342. if isfunction:
  343. if line.endswith('}'):
  344. isfunction = False
  345. functionname_sanatized = function_name.replace('$','').replace('[','').replace(']','').replace("'",'')
  346. functionlines.append(f':: {functionname_sanatized}_macro[widget]\n<<widget "{functionname_sanatized}">>\n')
  347. functionlines_temp = convert_lineblock(functionlines_temp)
  348. for fl in functionlines_temp:
  349. functionlines.append(f'\t{fl}')
  350. functionlines.append(f'<</widget>>\n')
  351. function_name_conversions.append([function_name,functionname_sanatized])
  352. else:
  353. functionlines_temp.append(line)
  354. continue
  355. if match := re.match(r"""(\$[a-z][a-z0-9\-_'"\[\]]+)\s*=\s*{""",line,re.I):
  356. isfunction = True
  357. #functionlines.append(f'<<widget "{match.group(1)}">>')
  358. function_name = match.group(1)
  359. functionlines_temp = []
  360. continue
  361. pv("AFTER FUNCTIONS:",line)
  362. while fuckyoumatch := re.search(r"""\[["']([^\]]*?)<<(.*?)>>(.*?)["']\]""",line):
  363. index = f'${fuckyoumatch.group(2)}'
  364. #left = ''
  365. if fuckyoumatch.group(1):
  366. index = f"'{fuckyoumatch.group(1)}'+" + index
  367. #right = ''
  368. if fuckyoumatch.group(3):
  369. index = index + f"+'{fuckyoumatch.group(3)}'"
  370. # right = fuckyoumatch.group(3)
  371. #index = f"'{left}'+${fuckyoumatch.group(2)}+'{right}'"
  372. #print(index)
  373. line = line.replace(fuckyoumatch.group(0),f"[{index}]")
  374. #print("MATCH")
  375. pv("AFTER ARRAY []:",line)
  376. while dynevalmatch := re.search(r"""dyneval\s*\(\s*'\s*RESULT\s*=\s*(<<.*?)'\s*\)""",line):
  377. fullmatch = dynevalmatch.group(0)
  378. varname = dynevalmatch.group(1)
  379. varname = varname.replace(r"[''",r"['").replace(r"'']",r"']")
  380. varname = "State.getVar('$"+varname.replace('<<',"'+").replace('>>',"+'")+"')"
  381. line = line.replace(fullmatch,varname)
  382. #print(line)
  383. pv("AFTER DYNEVAL:",line)
  384. while dynevalmatch := re.search(r"""dyneval\s*\(\s*'\s*RESULT\s*=\s*\$?(.*?)'\s*\)""",line):
  385. fullmatch = dynevalmatch.group(0)
  386. varname = "$"+dynevalmatch.group(1)
  387. varname = varname.replace('<<',"'+").replace('>>',"+'")
  388. #varname = varname.replace(r"[''",r"['").replace(r"'']",r"']")
  389. varname = varname.replace("['+","[").replace(r"+']",r"]")
  390. varname = varname.replace('$$',"$")
  391. line = line.replace(fullmatch,varname)
  392. pv("AFTER DYNEVAL2:",line)
  393. if line.startswith('!{') or line.startswith('!!{') or line == '!!{':
  394. line_output = '<!-- ' + line
  395. if line.endswith('}'):
  396. line_output += ' -->'
  397. else:
  398. commenting = True
  399. pv("IS COMMENT:",line_output)
  400. elif line.endswith('}') and commenting:
  401. line_output = line+' -->'
  402. commenting = False
  403. pv("IS COMMENT:",line_output)
  404. elif commenting:
  405. line_output = line.replace('--','-')
  406. pv("IS COMMENT:",line_output)
  407. elif line.lower() == 'end' or line.lower().startswith('end &!'):
  408. whitespace_count -= 1
  409. if len(nesting) > 0:
  410. end_command = nesting.pop()
  411. if end_command == 'if':
  412. #file.write('<</if>>\n')
  413. line_output = '<</if>>'
  414. elif end_command == 'while':
  415. #file.write('<</while>>\n')
  416. line_output = '<</while>>'
  417. elif end_command == 'act':
  418. #file.write('<</act>>\n')
  419. line_output = '<</act>>'
  420. else:
  421. print(f'ERROR: UNKNOWN NESTRING: {end_command}')
  422. else:
  423. line_output = '<</END>>'
  424. pv("IS END:",line_output)
  425. elif line.startswith('!'):
  426. line_output = '<!-- ' + line + '-->'
  427. pv("IS COMMENT:",line_output)
  428. elif line.lower() == 'else':
  429. #file.write('<<else>>\n')
  430. line_output = '<<else>>'
  431. whitespace_count -= 1
  432. pv("IS ELSE:",line_output)
  433. elif line.lower() == 'cls':
  434. line_output = ''
  435. pv("IS CLS:",line_output)
  436. elif line.lower() == '*nl':
  437. #file.write('\n')
  438. line_output = ''
  439. pv("IS NL:",line_output)
  440. elif line[0:3] == '---':
  441. line_output = ''
  442. pv("IS EOF:",line_output)
  443. elif match := re.match(r"^\s*msg\s*'(.*)'\s*$",line,re.I):
  444. msg = match.group(1).replace("'",'"')
  445. line_output = f"""<<msg '{msg}'>>"""
  446. pv("IS MSG:",line_output)
  447. elif match := re.match(r"""act\s*'(.*?)\s*\(<font color="red"><<will_cost>> Willpower</font>\)':\s*'<br><font color="red">You don''t have enough willpower to use this action.</font>'""",line,re.I):
  448. label = match.group(1).replace("'",'"')
  449. line_output = f"<<act `'{label} ('+$will_cost+')'`>><font color=red><br/>You don`t have enough willpower to use this action.</font><</act>>"
  450. elif match := re.match(r"""^'(?:<center>)?<img\s+(?:<<\$?\w+>>\s+)src="images\/([\w\/\.]+)(?:'\s*\+\s*rand\((\d+,\d+)\)\s*\+\s*')?([\w\/\.]+)"\s*>(?:<\/center>)?'""",line,re.I):
  451. #Images
  452. if match.group(2):
  453. line_output = f'''<<image "{match.group(1)}#{match.group(3)}" {match.group(2).replace(',',' ')}>>'''
  454. else:
  455. line_output = f'''<<image "{match.group(1)}{match.group(3)}">>'''
  456. pv("IS IMAGE:",line_output)
  457. elif match := re.match(r"""^'?(?:<center>)?<video\s+(?:<<\$?\w+>>\s+)*(?:\s*autoplay\s*|\s*loop\s*)*src="images\/([\w\/\.]+)(?:'\s*\+\s*rand\((\d+,\d+)\)\s*\+\s*')?([\w\/\.]+)"\s*>(?:<\/video>)?(?:<\/center>)?'?""",line,re.I):
  458. #Images
  459. if match.group(2):
  460. line_output = f'''<<video "{match.group(1)}#{match.group(3)}" {match.group(2).replace(',',' ')}>>'''
  461. else:
  462. line_output = f'''<<video "{match.group(1)}{match.group(3)}">>'''
  463. pv("IS VIDEO:",line_output)
  464. elif line.startswith('<') and line.endswith('>'):
  465. line_output = line
  466. pv("IS HTML:",line_output)
  467. elif line.startswith("'<") and line.endswith(">'"):
  468. line_output = line[1:-1]
  469. pv("IS COMMENTED HTML:",line_output)
  470. elif match := re.match(r"""^'[\w<>\s=:'"\/\.\(\),\*]+'$""",line):
  471. #Plain HTML
  472. line_output = line[1:-1]
  473. if link_match := re.findall(r"""(<a href="exec:([^"]+)">([^<]+)<\/a>)""",line_output):
  474. #line_output = #line_output.replace(link_match[0],"moep")
  475. #print("moep")
  476. #print(link_match)
  477. for lmatch in link_match:
  478. line_output = line_output.replace(lmatch[0],f"""<<link "{lmatch[2]}">>{convert_command(lmatch[1])}<</link>>""")
  479. pv("IS PLAIN HTML:",line_output)
  480. elif match := re.match(r"^\s*(if|while)\s+([^:]+):(.*)",line,re.I):
  481. command = match.group(1).lower()
  482. line_w = f'<<{command} {convert_condition(match.group(2))}>>'
  483. if match.group(3):
  484. #if com := convert_command(match.group(3)):
  485. # line_w += '\n' + (whitespace_count+1) * '\t' + com
  486. #else:
  487. # line_w += '\n' + (whitespace_count+1) * '\t' + convert_literal(match.group(3))
  488. converted = convert_lineblock([match.group(3)])
  489. if len(converted)>0 and converted[0]:
  490. line_w += '\n' + (whitespace_count+1) * '\t' + converted[0]
  491. line_w += '\n' + whitespace_count * '\t'+f'<</{command}>>'
  492. else:
  493. nesting.append(command)
  494. #file.write(line_w)
  495. line_output = line_w
  496. pv("IS IF:",line_output)
  497. elif match := re.match(r"\s*(act)\s*(.+):(.*)",line,re.I):
  498. # Act-Command
  499. command = match.group(1).lower()
  500. line_w = f'<<{command} {convert_literal(match.group(2))}>>'
  501. if match.group(3):
  502. line_w += '\n' + (whitespace_count+1) * '\t'+convert_command(match.group(3))
  503. line_w += '\n' + whitespace_count * '\t'+f'<</{command}>>'
  504. else:
  505. nesting.append(command)
  506. #file.write(line_w)
  507. line_output = line_w
  508. pv("IS ACT:",line_output)
  509. elif match := re.match(r"\s*(elseif)\s+([^:]+):(.*)",line,re.I):
  510. # ElseIf
  511. command = match.group(1).lower()
  512. line_w = f'<<{command} {convert_condition(match.group(2))}>>'
  513. whitespace_count -= 1
  514. if match.group(3):
  515. #line_w += '\n' + (whitespace_count+1) * '\t'+convert_command(match.group(3))
  516. line_w += '\n' + whitespace_count * '\t'+f'<</if>>'
  517. #nesting.pop()
  518. #file.write(line_w)
  519. line_output = line_w
  520. pv("IS ELSEIF:",line_output)
  521. #elif match := re.match(r"^dynamic\s+'(.*)'$",line,re.I):
  522. # out = match.group(1).replace('<<',"'+").replace('>>',"+'")
  523. # line_output = f"<<dynamic {out}>>"
  524. elif match := re.match(r"^dynamic '\$?(.*?)\s*([\+\-]?=)\s*(.*?)\s*'$",line,re.I):
  525. left = match.group(1)
  526. right = match.group(3)
  527. operator = match.group(2)
  528. left = left.replace(r"[''",r"['").replace(r"'']",r"']")
  529. left = left.replace(r"['+",r"[").replace(r"+']",r"]")
  530. left = left.replace('<<',"'+").replace('>>',"+'")
  531. left = left.replace('$$',"$")
  532. right = right.replace(r"[''",r"['").replace(r"'']",r"']")
  533. right = right.replace(r"['+",r"[").replace(r"+']",r"]")
  534. right = right.replace('<<',"").replace('>>',"")
  535. right = right.replace('$$',"$")
  536. right = convert_literal(right)
  537. line_output = f'<<set {left} {operator} {right}>>'
  538. pv("IS DYNAMIC:",line_output)
  539. #elif match := re.match(r"^dynamic '\$?(.*?)\s*([\+\-]?=)\s*(.*?)\s*'$",line,re.I):
  540. elif match := re.match(r"^dynamic\s*\$([a-zA-Z]\w+)$",line,re.I):
  541. line_output = f'<<{match.group(1)}>>'
  542. elif match := re.match(r"""^([^\$])*<a\s+href\s*=\s*"exec:\s*(?:minut\s*\+=\s*(\d+)\s*&\s*)?gt(.*)?"\s*>(.*?)</a>.*$""",line,re.I):
  543. while link_match := re.search(r"""<a\s+href\s*=\s*"exec:\s*(?:minut\s*\+=\s*(\d+)\s*&\s*)?gt(.*)?"\s*>(.*?)</a>""",line,re.I):
  544. full_match = link_match.group(0)
  545. time = ""
  546. if link_match.group(1):
  547. time = f"<<set $minut += {link_match.group(1)}>>"
  548. goto = link_match.group(2)
  549. goto = goto.replace(","," ").replace(r"''",r"'")
  550. label = link_match.group(3)
  551. link = f"<<link '{label}'>>{time}<<gt {goto}>><</link>>"
  552. line = line.replace(full_match,link)
  553. line_output = line
  554. elif match := convert_command(line):
  555. line_output = match
  556. pv("IS COMMAND:",line_output)
  557. else:
  558. line_output = convert_literal(line)
  559. if len(line_output) >= 2 and line_output[0] == '\'' and line_output[-1] == '\'':
  560. line_output = f'<p>{line_output[1:-1]}</p>'
  561. pv("IS LITERAL:",line_output)
  562. whitespace = whitespace_count * '\t'
  563. output = f'{whitespace}{line_output}\n'
  564. if output.strip():
  565. #file.write(cleanUpTheMess(output))
  566. output = cleanUpTheMess(output)
  567. if "ERROR:" in output:
  568. global error_counter
  569. output = f'{whitespace}<!-- FAILED TO CONVERT\n{whitespace}\t{original}\n{whitespace}-----\n\t{output}\n{whitespace}-->\n{whitespace}<<warn "CONVERSION ERROR {(hashlib.md5(original.encode())).hexdigest()}">>\n'
  570. error_counter += 1
  571. outputs.append(output)
  572. for subpassId in subpassages:
  573. subpass = subpassages[subpassId]
  574. subpassageLines = convert_lineblock(subpass)
  575. outputs.append(f'\n:: {subpassId}\n')
  576. for subpassageLine in subpassageLines:
  577. outputs.append(subpassageLine)
  578. if len(functionlines) > 0:
  579. #outputs.append(f'::{location_identifier}_widgets[widget]\n')
  580. for functionline in functionlines:
  581. functionline = functionline.replace('$ARGS','_args').replace('$location_var[$here][','_args[')
  582. outputs.append(functionline)
  583. return outputs
  584. def convert_file(filename,skipIfNotExplicit=0,defaultsubfolder=False):
  585. skip = skipIfNotExplicit
  586. qsp_filename = filename+".qsrc"
  587. qsp_filepath = os.path.join(qsp_sources_path,qsp_filename)
  588. tw_filename = filename+".tw"
  589. tw_filepath = os.path.join(tw_sources_path,tw_filename)
  590. if defaultsubfolder:
  591. os.makedirs(os.path.join(tw_sources_path,defaultsubfolder),exist_ok =True)
  592. tw_filepath = os.path.join(tw_sources_path,defaultsubfolder,tw_filename)
  593. try:
  594. with open(qsp_filepath) as file:
  595. lines = [line.rstrip() for line in file]
  596. except:
  597. try:
  598. with open(qsp_filepath, encoding="utf-8") as file:
  599. lines = [line.rstrip() for line in file]
  600. except:
  601. return f"FAILED: {qsp_filename}"
  602. location_identifier = ''
  603. ignore_recusions = 0
  604. if match := re.match(r"^\s*!!\s*(FOLDER\s*:\s*\w+)?\s*(SKIP\s*:\s*-?\d)?\s*(IGNORERECURSIONS\s*:\s*-?\d)?\s*$",lines[0],re.I):
  605. if match.group(1):
  606. parts = match.group(1).split(':')
  607. new_path = os.path.join(tw_sources_path,parts[1].strip())
  608. os.makedirs(new_path,exist_ok =True)
  609. tw_filepath = os.path.join(new_path,tw_filename)
  610. if match.group(2):
  611. parts = match.group(2).split(':')
  612. arg = int(parts[1])
  613. if arg == 1:
  614. skip = 1
  615. elif arg == 0:
  616. skip = 0
  617. elif arg == -1:
  618. skip = -1
  619. if match.group(3):
  620. parts = match.group(3).split(':')
  621. arg = int(parts[1])
  622. if arg == 1:
  623. ignore_recusions = 1
  624. elif arg == 0:
  625. ignore_recusions = 0
  626. if skip == 1:
  627. return
  628. if skip == -1 and os.path.exists(tw_filepath):
  629. modification_time_delta = os.path.getmtime(qsp_filepath) - os.path.getmtime(tw_filepath)
  630. if modification_time_delta <= 0:
  631. return
  632. identifier_line = 0
  633. for line_num in range(0,len(lines)-1):
  634. line_raw = lines[line_num]
  635. line = line_raw.strip()
  636. match = re.match(r"#\s*(\S+)", line)
  637. if match:
  638. location_identifier = match.group(1)
  639. identifier_line = line_num
  640. break
  641. with open(tw_filepath, 'w') as file:
  642. #file.write(f'<!-- GENERATED: {datetime.datetime.now()} -->\n')
  643. file.write(f':: {location_identifier}\n')
  644. file.write(f"<<set $here = '{location_identifier}'>>\n<<set $ARGS = $location_var[$here]>>\n")
  645. if ignore_recusions == 1:
  646. file.write(f'<<set _ts to Math.floor(Date.now() / 10000)>>\n')
  647. file.write(f'<<setinit $gt_history[_ts][$here] = 0>>\n')
  648. #for line_num in range(identifier_line+1,len(lines)-1):
  649. outputs = convert_lineblock(lines[identifier_line+1:],location_identifier)
  650. for output in outputs:
  651. file.write(output)
  652. with open(tw_filepath, 'r') as file:
  653. data = file.read()
  654. with open(tw_filepath, 'w') as file:
  655. regex1 = r"""<<gs 'willpower' ([\s'\w]*)>>\s*<<if \$will_cost <= \$pc\.pcs_willpwr>>\s*<<act '([\w\s]*?)\s*\(will_cost Willpower\)'>>"""
  656. while match := re.search(regex1,data,re.I):
  657. blockStart = match.end()
  658. regex_close = r"""<<else>>\s*<<act `?'"""+match.group(2)+r""".*?<</act>>\s*<</if>>"""
  659. if close_match := re.search(regex_close,data,re.I):
  660. blockEnd = close_match.start()
  661. block = data[blockStart:blockEnd]
  662. # Remove the re-calculation of the willpower-cost
  663. newBlock = block
  664. newBlock = newBlock.replace("<<gs 'willpower' "+match.group(1)+">>",'')
  665. newBlock = re.sub(r"""<<gs 'willpower' 'pay' ([\s'\w]*)>>""","",newBlock)
  666. data = data.replace(block,newBlock)
  667. data = data.replace(close_match.group(0),"")
  668. arguments = match.group(1).replace(' ',',')
  669. data = data.replace(match.group(0),"<<act '"+match.group(2)+"' `{willpower:["+arguments+"]}`>>")
  670. else:
  671. print("FAIL: "+match.group(0))
  672. break
  673. file.write(data)
  674. print(f"Completed {filename}")
  675. return tw_filepath
  676. FTCL = [r'ERROR: FAILED TO CONVERT LITERAL:\s*"""',r'"""']
  677. VAR = r"""\$?([a-zA-Z][a-zA-Z0-9-_\[\]'"]+]*)"""
  678. preparations = [
  679. [
  680. r"""\$week\[""",
  681. r"$week_name["
  682. ],
  683. [
  684. r"""pcs_pubecol\[""",
  685. r"pcs_pubecol_num["
  686. ],
  687. [
  688. r"""pcs_pubes\[""",
  689. r"pcs_pubes_num["
  690. ],
  691. [
  692. r"""^PLAY\s*.*""",
  693. r""
  694. ],
  695. [
  696. r"""^\s*pl\s+(.*)$""",
  697. r"\1"
  698. ]
  699. #[
  700. # r"""(</?(?:table|center|th|tr|td))([^>]*=[^>]*)(>)""",
  701. # r'\1\3',
  702. # re.I
  703. #]
  704. ]
  705. replaces = [
  706. [
  707. r"ERROR: FAILED TO CONVERT CONDITION: func\(",
  708. r"func("
  709. ],
  710. [
  711. r"ERROR: FAILED TO CONVERT CONDITION: \$?([a-zA-Z])",
  712. r"$\1"
  713. ],
  714. [
  715. FTCL[0]+r"killvar\s*'"+VAR+r"'"+FTCL[1],
  716. r"<<set $\1 to undefined>>"
  717. ],
  718. [
  719. r"""<img\s+(<<\$set_imgh>>)?\s*src="([^<^\.]*)(<<\$?([a-zA-Z][a-zA-Z0-9-_\[\]'"\)\(),\s]+]*)>>)?(\.[^"]+)">""",
  720. r"<<image `'\2\3\5'`>>"
  721. ],
  722. [
  723. r"""'([\w\/]+)<<\s*rand\s*\(\s*(\-?\d+)\s*,\s*(\-?\d+)\s*\)\s*>>([^']*)'""",
  724. r"""'\1'+rand(\2,\3)+'\4'"""
  725. ],
  726. [
  727. r"""<<set \$?([a-zA-Z][a-zA-Z0-9-_'"]+]*\[.*)>>""",
  728. r"""<<setinit $\1>>"""
  729. ],
  730. [
  731. # <<set $gopnikbandQW += -1>> -> <<setn $gopnikbandQW += -1>>
  732. r"""<<set (\$[^>]*?)\s([+-]=)\s*(-?\d+)>>""",
  733. r"""<<setn \1 \2 \3>>""",
  734. 1
  735. ],
  736. [
  737. # asd
  738. r"""<<set (\$[^>]*?)\s(\+=)\s*(["'][^>]*?)>>""",
  739. r"""<<sets \1 \2 \3>>""",
  740. 1
  741. ],
  742. [
  743. r"""(\+)\s+=""",
  744. r"""\1="""
  745. ],
  746. [
  747. r"(I|you|You|he|He|she|She|it|It|we|We|they|They|can|Can|don|Don)''(m|re|s|ll|ve|t)",
  748. r"\1'\2"
  749. ],
  750. #[
  751. # r"^(.*"+FTCL[0]+r"(.*)"+FTCL[1]+r".*)$",
  752. # r"<!-- \1 -->\n<<warn 'FTCL: \1'>>"
  753. #],
  754. [
  755. r"=\s*\$(mid|MID)\s*\(",
  756. r"= mid("
  757. ],
  758. [
  759. r"(<<set\s*.*?\[)([a-zA-Z].*?)(\]\s*=.*>>)",
  760. r"\1$\2\3"
  761. ],
  762. [
  763. r"(<<act\s*'.*)(\$.*?\])(.*'>>)",
  764. r"\1'+\2+'\3"
  765. ],
  766. [
  767. r"\[([a-zA-Z]\w*)\]",
  768. r"[$\1]"
  769. ],
  770. [
  771. r"([\+\-])\s+=",
  772. r"\1="
  773. ],
  774. [
  775. r"<<setinit\s*(.*)\[\]\s*=\s*(.*)>>",
  776. r"""<<setinitpush "\1" \2>>"""
  777. ],
  778. [
  779. r"\s+min\(",
  780. r" Math.min("
  781. ],
  782. [
  783. r"\s+max\(",
  784. r" Math.max("
  785. ],
  786. [
  787. r"""<<set (.*) to null>>\s*,\s*(.*)(\s*)""",
  788. r"<<set \1[\2] to null>>\3"
  789. ]
  790. ,
  791. [
  792. r"""\$arrsize\(""",
  793. r"arrsize("
  794. ],
  795. [
  796. r"""<<set(?:init)?\s+\$?(?P<name>\w+)\[arrsize\('\$?(?P=name)'\)\]\s*=\s*(.*)\s*>>""",
  797. r"<<run $\1.push(\2)>>"
  798. ],
  799. [
  800. r"""<center><(?:h\d|b)><font color="maroon">(.*)</font></(?:h\d|b)></center>""",
  801. r"<h2>\1</h2>"
  802. ],
  803. [
  804. r"""(<<act '[^']*)'([^']*'>>)""",
  805. r"\1`\2"
  806. ],
  807. # NPC-Stuff Start
  808. [
  809. r"""\$npc_(\w*?)\[([^\]]*?)\]""",
  810. r"$npcs.get(\2,'\1')",
  811. 1
  812. ],
  813. # Fix for Sub-Arrays
  814. [
  815. r"""\$npcs\.get\((.*?),('\w*')\)(\[[^\]]*\]+?)\]""",
  816. r"$npcs.get(\1]\3,\2)",
  817. 1
  818. ],
  819. [
  820. r"""<<set(?:init)?\s+\$npcs\.get\((.*?)\)\s*=\s*(.*?)>>""",
  821. r"<<run $npcs.set(\1,\2)>>",
  822. 1
  823. ],
  824. [
  825. r"""<<set(?:init)?\s+\$npcs\.get\((.*?)\)\s*\+=\s*(.*?)>>""",
  826. r"<<run $npcs.inc(\1,\2)>>",
  827. 1
  828. ],
  829. [
  830. r"""<<set(?:init)?\s+\$npcs\.get\((.*?)\)\s*-=\s*(.*?)>>""",
  831. r"<<run $npcs.dec(\1,\2)>>",
  832. 1
  833. ],
  834. # NPC-Stuff END
  835. [
  836. r"""(\$\w+(?:\['\w+'\])?)\s*(==|>=?|<=?|!=)\s*(\-?\d+)""",
  837. r"""getvar("\1") \2 \3""",
  838. 1
  839. ],
  840. [
  841. #Example: $property_construction_status[$i] == 0 -> getvar("$property_construction_status["+$i+"]") == 0
  842. r"""(\$\w+)(?:\[(\$\w+)\])\s*(==|>=?|<=?|!=)\s*(\-?\d+)""",
  843. r"""getvar("\1["+\2+"]") \3 \4""",
  844. 1
  845. ],
  846. [
  847. r"""\*?\s*\$\s*cl[ar]\s*$""",
  848. r""
  849. ],
  850. [
  851. r"""<<gs 'clothing' 'wear'\s*(.*?)\s+(.*?)>>""",
  852. r"<<run $wardrobe.wear_clothes_legacy('clothes',\1,\2)>>"
  853. ],
  854. [
  855. r"""<<gs 'shoes' 'wear'\s+(.*?)\s+(.*?)>>""",
  856. r"<<run $wardrobe.wear('shoes',\1,\2)>>"
  857. ],
  858. [
  859. r"""<<gs\s+'shoes'\s+'wear'\s+'last_worn'\s*>>""",
  860. r"<<run $wardrobe.wear_last('shoes')>>"
  861. ],
  862. [
  863. r"""<<gs\s+'bras'\s+'wear'\s+(.+?)\s+(.+?)\s*>>""",
  864. r"<<run $wardrobe.wear('bra',\1,\2)>>"
  865. ],
  866. [
  867. r"""<<gs\s+'panties'\s+'wear'\s+(.+?)\s+(.+?)\s*>>""",
  868. r"<<run $wardrobe.wear('panties',\1,\2)>>"
  869. ],
  870. [
  871. r"""<<gs\s+'coats'\s+'wear'\s+(.+?)\s+(.+?)\s*>>""",
  872. r"<<run $wardrobe.wear('coat',\1,\2)>>"
  873. ],
  874. [
  875. r"""<<gs\s+'bras'\s+'wear'\s*>>""",
  876. r"<<run $wardrobe.wear_last('bra')>>"
  877. ],
  878. [
  879. r"""<<gs\s+'panties'\s+'wear'\s*>>""",
  880. r"<<run $wardrobe.wear_last('panties')>>"
  881. ],
  882. [
  883. r"""iif\(([^)]*?)\s*==?\s*'',""",
  884. r"iif(!\1,",
  885. 1
  886. ],
  887. # Rand in gs Fix
  888. [
  889. r"""<<g([st].*?)\srand\((.*?)\)(.*?)>>""",
  890. r"<<g\1 `rand(\2)`\3>>",
  891. 1
  892. ],
  893. # Pain
  894. [
  895. r"""(<<(?:else)?if\s+|and\s+|x?or\s+)(?:getvar\(")\$pain\[('\w+')\](?:"\))(.*?>>)""",
  896. r"\1$pc.pain(\2)\3",
  897. 1
  898. ],
  899. [
  900. r"""<<set(?:init)?\s+\$pain\[('\w+')\]\s*\+=\s*(.*?)>>""",
  901. r"<<run $pc.painInc(\1,\2)>>",
  902. 1
  903. ],
  904. [
  905. r"""<<set(?:init)?\s+\$pain\[('\w+')\]\s*-=\s*(.*?)>>""",
  906. r"<<run $pc.painDec(\1,\2)>>",
  907. 1
  908. ],
  909. [
  910. r"""<<set(?:init)?\s+\$pain\[('\w+')\]\s*=\s*(.*?)>>""",
  911. r"<<run $pc.painSet(\1,\2)>>",
  912. 1
  913. ],
  914. #Cum
  915. [
  916. r"""\$cumloc\[(\d+)\]""",
  917. r"$pc.cumAtLocation(\1)",
  918. 1
  919. ],
  920. ]
  921. purge_messes=[
  922. r"""<<set(init)? \$npc_selfie\[""",
  923. r'''<<set(init)? \$npcGo\[''', # We need to replace this by another function,
  924. r'''<<set(init)? \$npcGoSchool\['''
  925. ]
  926. def cleanUpTheMess(output):
  927. for purge_mess in purge_messes:
  928. if match := re.search(purge_mess,output):
  929. return ''
  930. for replace in replaces:
  931. if len(replace) > 2:
  932. if replace[2] == 1:
  933. while(re.search(replace[0],output)):
  934. output = re.sub(replace[0],replace[1],output)
  935. else:
  936. output = re.sub(replace[0],replace[1],output)
  937. if warnmatch := re.search(r"""<<warn '(.*)'>>""",output):
  938. return output.replace(warnmatch.group(1),warnmatch.group(1).replace("'",'"'))
  939. if link_match := re.findall(r"""(<a href="exec:([^"]+)">([^<]+)<\/a>)""",output):
  940. for lmatch in link_match:
  941. output = output.replace(lmatch[0],f"""<<link "{lmatch[2]}">>{convert_command(lmatch[1])}<</link>>""")
  942. output = re.sub(r"""\$result""","$result",output,0,re.I)
  943. while image_match := re.match(r"""<img\s+(<<\$set_imgh>>)?\s*src="([^<^\.]*)(<<\$?([a-zA-Z][a-zA-Z0-9-_\[\]'"]+]*)>>)?\.[^"]+">""",output):
  944. if len(image_match.group(3)) == 0:
  945. break
  946. output = output.replace(image_match.group(3),f'"+${image_match.group(4)}+"')
  947. while match := re.search(r"""<<set(?:init)?[^=]+=\s*'([a-zA-Z0-9\.\?!<>"\s,`\-\(\)]+)('([a-zA-Z0-9\.\?!<>"\s,`\-\(\)]+))+'>>""",output):
  948. output = output.replace(match.group(2),f"`{match.group(3)}")
  949. # NPCs: add print to all get-calls which are not inside a macro
  950. if(not output.strip().startswith('<<')):
  951. output = re.sub(r"(?<!=)(\$npcs\.get\(.*?\))",r"<<=\1>>",output)
  952. for variable_replacement in variables.variable_replacements:
  953. if len(variable_replacement) > 2:
  954. if variable_replacement[2] == 1:
  955. output = re.sub(variable_replacement[0],variable_replacement[1],output)
  956. else:
  957. output = output.replace(variable_replacement[0],variable_replacement[1])
  958. else:
  959. output = output.replace(variable_replacement[0],variable_replacement[1])
  960. output = output.replace("$location_var[$here][0] == ''","!$location_var[$here][0]")
  961. return output
  962. test_line = ''
  963. #test_line = """gs 'npc_relationship', 'socialgroup_setting', 0, 0, -10, 10, -10, -10"""
  964. if len(test_line) > 0:
  965. verbose = True
  966. print(test_line)
  967. result = convert_lineblock([test_line])
  968. if len(result) > 0:
  969. print(result[0])
  970. else:
  971. print("EMPTY RESULT")
  972. exit()
  973. qsp_sources_path = "locations"
  974. tw_sources_path = os.path.join("sugarcube","src","autogenerated")
  975. output_files = []
  976. os.makedirs(tw_sources_path, exist_ok=True)
  977. #for replace in replaces:
  978. # print(replace[0])
  979. restrictfiles = []
  980. #restrictfiles = ['LakeBoyDy']
  981. for file in os.listdir(qsp_sources_path):
  982. if len(restrictfiles) == 0 or (os.path.splitext(file)[0] in restrictfiles):
  983. if file.endswith(".qsrc"):
  984. output_files.append(convert_file(os.path.splitext(file)[0],skipMode,'unsorted'))
  985. print(len(function_name_conversions))
  986. #for output_file in output_files:
  987. # for line in fileinput.input(output_file, inplace=True):
  988. #
  989. # for function_name_conversion in function_name_conversions:
  990. #
  991. #
  992. # if fileinput.filelineno() == 10:
  993. # print(('10'+line), end='')
  994. # break