2626 # showing an error.
2727use_ifs = True # Whether to evaluate preprocessor if statements
2828
29+ verbose = False
30+
2931# Default options to pass to the compiler
3032port = "/dev/ttyUSB0"
3133chip = "08m2" # Must be lowercase m or x if included
@@ -52,6 +54,7 @@ def print_help():
5254 -s, --syntax Send the file to the compiler for a syntax check only (no download)
5355 --nocolor Disable terminal colour for systems that do not support it (Windows).
5456 --noifs Disable evaluation of #if and #ifdef - this will be left to the compiler if present.
57+ --verbose Print preproccessor debugging info
5558 -h, --help Display this help
5659
5760Optional switches only used if sending to the compiler
@@ -91,6 +94,7 @@ def main(argv):
9194 global compiler_path
9295 global use_colour
9396 global use_ifs
97+ global verbose
9498
9599 # Use the last argument as the file name if it does not start with a dash
96100 if (len (argv ) == 1 or len (argv ) >= 2 and argv [- 2 ] not in ("-o" , "-v" , "-c" )) and argv [- 1 ][0 ] != "-" : # Double check the second last is -i if needed
@@ -101,7 +105,7 @@ def main(argv):
101105 argv .pop () # Remove the -i option as it has been parsed here.
102106
103107 try :
104- opts , _ = getopt .getopt (argv ,"hi:o:uv:sfc:detpP:" ,["help" , "ifile=" ,"ofile=" ,"upload" ,"variant=" ,"syntax" ,"firmware" ,"comport=" ,"debug" ,"debughex" ,"edebug" ,"edebughex" ,"term" ,"termhex" ,"termint" , "pass" , "tidy" , "compilepath=" , "nocolor" , "noifs" ])
108+ opts , _ = getopt .getopt (argv ,"hi:o:uv:sfc:detpP:" ,["help" , "ifile=" ,"ofile=" ,"upload" ,"variant=" ,"syntax" ,"firmware" ,"comport=" ,"debug" ,"debughex" ,"edebug" ,"edebughex" ,"term" ,"termhex" ,"termint" , "pass" , "tidy" , "compilepath=" , "nocolor" , "noifs" , "verbose" ])
105109 except getopt .GetoptError :
106110 print_help ()
107111 sys .exit (2 )
@@ -148,6 +152,9 @@ def main(argv):
148152 tidy = True
149153 elif opt in ("-P" , "--compilepath" ): #chose non-default path to compilers
150154 compiler_path = os .path .join (arg ,'' ) #adds trailing slash if needed
155+ elif opt in ("--verbose" ): # Print out info as the preproccessor is running
156+ verbose = True
157+
151158 if not os .path .exists (inputfilename ):
152159 if (inputfilename == "main.bas" ): #show help if likely run with no arguments
153160 preprocessor_error ("'{}/{}' does not exist. Either specify an input file or put it in the same folder as this script with the name 'main.bas'" .format (os .getcwd (), inputfilename ), True )
@@ -207,7 +214,7 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
207214 global chip
208215 global port
209216 savingmacro = False
210- print ("\n Including file " + curfilename )
217+ preprocessor_info ("\n Including file " + curfilename )
211218 path = os .path .dirname (os .path .abspath (inputfilename ))+ "/"
212219 if curfilename .startswith ("/" ): #decide if an absolute or relative path
213220 curpath = ""
@@ -255,13 +262,13 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
255262 key = workingline .replace ("'" , " " ).replace (";" , " " ).strip ().split ()[1 ]
256263 active = is_if_active (0 ) and key in definitions
257264 if_stack .append ((active , active ))
258- print ("{}: #ifdef. Stack is now: {}" .format (count + 1 , if_stack ))
265+ preprocessor_info ("{}: #ifdef. Stack is now: {}" .format (count + 1 , if_stack ))
259266 line = "; {}" .format (line )
260267 elif use_ifs and workingline .lower ().startswith ("#ifndef" ):
261268 key = workingline .replace ("'" , " " ).replace (";" , " " ).strip ().split ()[1 ]
262269 active = is_if_active (0 ) and key not in definitions
263270 if_stack .append ((active , active ))
264- print ("{}: #ifndef. Stack is now: {}" .format (count + 1 , if_stack ))
271+ preprocessor_info ("{}: #ifndef. Stack is now: {}" .format (count + 1 , if_stack ))
265272 line = "; {}" .format (line )
266273 # Ifs will be treated separately later after definitions are substituted.
267274 elif use_ifs and workingline .lower ().startswith ("#elseifdef" ): # ELSE and ELSEIF
@@ -272,7 +279,7 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
272279 active = is_if_active (1 ) and not if_stack [- 1 ][1 ] and key in definitions
273280 if_stack [- 1 ] = (active , if_stack [- 1 ][1 ] or active )
274281 line = "; {}" .format (line )
275- print ("{}: #elseifdef. Stack is now: {}" .format (count + 1 , if_stack ))
282+ preprocessor_info ("{}: #elseifdef. Stack is now: {}" .format (count + 1 , if_stack ))
276283 elif use_ifs and workingline .lower ().startswith ("#elseifndef" ):
277284 if len (if_stack ) == 0 :
278285 preprocessor_error ("""Too many elses or not enough ifs.
@@ -281,13 +288,13 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
281288 active = is_if_active (1 ) and not if_stack [- 1 ][1 ] and key not in definitions
282289 if_stack [- 1 ] = (active , if_stack [- 1 ][1 ] or active )
283290 line = "; {}" .format (line )
284- print ("{}: #elseifndef. Stack is now: {}" .format (count + 1 , if_stack ))
291+ preprocessor_info ("{}: #elseifndef. Stack is now: {}" .format (count + 1 , if_stack ))
285292 elif use_ifs and workingline .lower ().startswith ("#else" ) and len (workingline .strip ().split ()[0 ]) == 5 : # Else only - not elseif
286293 if len (if_stack ) == 0 :
287294 preprocessor_error ("""Too many elses or not enough ifs.
288295 Error is before or at line {} in '{}'.""" .format (count + 1 ,curfilename ))
289296 if_stack [- 1 ] = (is_if_active (1 ) and not if_stack [- 1 ][1 ], True )
290- print ("{}: #else. Stack is now: {}" .format (count + 1 , if_stack ))
297+ preprocessor_info ("{}: #else. Stack is now: {}" .format (count + 1 , if_stack ))
291298 # elsif only will be evaluated after definitions are substituted.
292299 line = "; {}" .format (line )
293300 elif use_ifs and workingline .lower ().startswith ("#endif" ):
@@ -296,7 +303,7 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
296303 Error is before or at line {} in '{}'.""" .format (count + 1 ,curfilename ))
297304 else :
298305 if_stack .pop ()
299- print ("{}: #endif. Stack afterwards is: {}" .format (count + 1 , if_stack ))
306+ preprocessor_info ("{}: #endif. Stack afterwards is: {}" .format (count + 1 , if_stack ))
300307 line = "; {}" .format (line )
301308 elif workingline .lower ().startswith ("#undef" ): # Put undef up here so that substitutions happen afterwards
302309 workingline = workingline [7 :].lstrip ().split ("'" )[0 ].split (";" )[0 ].rstrip ()
@@ -311,9 +318,9 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
311318 # Substitute defines (before it is added so that the define itself is not replaced)
312319 for key ,value in definitions .items ():
313320 if key in line :
314- print ("Replacing '{}' with " .format (line .strip ()), end = "" )
321+ preprocessor_info ("Replacing '{}' with " .format (line .strip ()), end = "" )
315322 line = replace (key , value ,line ) # Replace whole words only that are not in strings or comments
316- print ("'{}'" .format (line .strip ()))
323+ preprocessor_info ("'{}'" .format (line .strip ()))
317324 # line=line+" 'DEFINE: "+value+" SUBSTITUTED FOR "+key+"\n"
318325 for key , macrovars in macros .items ():
319326 if key in line :
@@ -329,12 +336,17 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
329336
330337 macrocontents = macrocontents .split ("," )[1 ].strip () # Remove the first parameter nd try again
331338 else :
332- print ("finished parsing macro contents" )
339+ preprocessor_info ("finished parsing macro contents" )
333340 params [argnum ]= macrocontents .split ("," )[0 ].rstrip ()
334- print (params )
341+ preprocessor_info (params )
335342 break
336343 line = replace (key , macrovars [0 ], line )
337- print (macrovars )
344+
345+ # # Make sure each line is commented out in a multiline macro if the surrounding code should be commented out
346+ if not is_if_active (0 ):
347+ line = line .replace ("\n " , "\n ; " )
348+
349+ preprocessor_info (macrovars )
338350 for num , name in macrovars .items ():
339351 if name in line :
340352 if num > 0 :
@@ -345,21 +357,21 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
345357 active = is_if_active (1 ) and evaluate_basic (line .lstrip ()[4 :], count + 1 , curfilename )
346358 if_stack .append ((active , active ))
347359 line = "; {}" .format (line )
348- print ("{}: #if. Stack is now: {}" .format (count + 1 , if_stack ))
360+ preprocessor_info ("{}: #if. Stack is now: {}" .format (count + 1 , if_stack ))
349361 elif use_ifs and workingline .lower ().startswith ("#elseif " ):
350362 if len (if_stack ) == 0 :
351363 preprocessor_error ("""Not enough ifs.
352364 Error is before or at line {} in '{}'.""" .format (count + 1 ,curfilename ))
353365 active = is_if_active (1 ) and not if_stack [- 1 ][1 ] and evaluate_basic (line .lstrip ()[8 :], count + 1 , curfilename )
354366 if_stack [- 1 ] = (active , if_stack [- 1 ][1 ] or active )
355- print ("{}: #elseif. Stack is now: {}" .format (count + 1 , if_stack ))
367+ preprocessor_info ("{}: #elseif. Stack is now: {}" .format (count + 1 , if_stack ))
356368
357369 if is_if_active (0 ):
358370 # Preprocessor check
359371 if workingline .lower ().startswith ("#include" ):
360372 workingline = workingline [9 :].lstrip ().split ("'" )[0 ].split (";" )[0 ].rstrip () #remove #include text, comments, and whitespace
361373 workingline = workingline .strip ('"' ) #remove quotation marks around path
362- #print (workingline)
374+ #preprocessor_info (workingline)
363375 with open (outputfilename , 'a' ) as output_file :
364376 output_file .write ("'---BEGIN " + workingline + " ---\n " )
365377 progparse (workingline ,count + 1 ,curfilename ) # +1 for 0 indexing
@@ -368,7 +380,7 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
368380 try :
369381 definitions [workingline .split ()[0 ]]= (workingline .split (None ,1 )[1 ]) #add to dictionary of definitions
370382 except :
371- print ("Old define found, leaving intact" )
383+ preprocessor_info ("Old define found, leaving intact" )
372384 # Make it replace any call to itdelf with itself so that it is in the dictionary for ifdef
373385 definitions [workingline .split ()[0 ]] = workingline .split ()[0 ]
374386
@@ -384,14 +396,14 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
384396 elif workingline .lower ().startswith ("#com" ): # Set the serial port
385397 port = workingline [5 :].lstrip ().split ("'" )[0 ].split (";" )[0 ].rstrip () # Remove #com text, comments, and whitespace
386398 port = port .strip ('"' ) #remove quotation marks around path
387- print ("Setting serial port to '{}'" .format (port ))
399+ preprocessor_info ("Setting serial port to '{}'" .format (port ))
388400 with open (outputfilename , 'a' ) as output_file :
389401 output_file .write (line .rstrip ()+ " 'SERIAL PORT PARSED\n " )
390402 elif workingline .lower ().startswith ("#macro" ): #Automatically substitute #macros
391403 savingmacro = True
392404 workingline = workingline [7 :].lstrip ().split ("'" )[0 ].split (";" )[0 ].rstrip ()
393405 macroname = workingline .split ("(" )[0 ].rstrip ()
394- print (macroname )
406+ preprocessor_info (macroname )
395407 with open (outputfilename , 'a' ) as output_file :
396408 output_file .write ("'PARSED MACRO " + macroname )
397409 macrocontents = workingline .split ("(" )[1 ].rstrip ()
@@ -400,17 +412,17 @@ def progparse(curfilename, called_from_line=None, called_from_file=None):
400412 while (1 ):
401413 argnum += 1
402414 if macrocontents .strip ()== ")" :
403- print ("no parameters to macro" )
404- macros [macroname ][0 ]= "'Start of macro: " + macroname
405- print (macros )
415+ preprocessor_info ("no parameters to macro" )
416+ macros [macroname ][0 ]= "'Start of macro: " + macroname + " \n "
417+ preprocessor_info (macros )
406418 break
407419 else :
408420 macrocontents = macrocontents .rstrip (")" ).strip ("(" )
409421 macros [macroname ][argnum ]= macrocontents .split ("," )[0 ].rstrip () #create spot in dictionary for macro variables, but don't populate yet
410422 if "," in macrocontents :
411423 macrocontents = macrocontents .split ("," )[1 ].strip ().rstrip ()
412424 else :
413- print ("finished parsing macro contents" )
425+ preprocessor_info ("finished parsing macro contents" )
414426 macros [macroname ][0 ]= "'--START OF MACRO: " + macroname + "\n "
415427 break
416428 elif savingmacro == True :
@@ -502,7 +514,7 @@ def set_chip(new_chip: str) -> None:
502514 "28x2" , "40x2" ]
503515 new_chip = new_chip .lower () # In case of 08M2 or 08m2
504516 if new_chip in valid_chips :
505- print ("Setting the PICAXE chip to: '{}'" .format (new_chip ))
517+ preprocessor_info ("Setting the PICAXE chip to: '{}'" .format (new_chip ))
506518 chip = new_chip
507519 if (chip == "40x2" ):
508520 chip = "28x2" #28x2 and 40x2 use the same compiler
@@ -542,6 +554,10 @@ def preprocessor_warning(msg):
542554 print ("\u001b [0m" , end = "" ) # Reset
543555 print (msg )
544556
557+ def preprocessor_info (* values , ** kwargs ):
558+ """ Prints an info message if in verbose mode, otherwise does nothing. """
559+ if verbose :
560+ print (* values , ** kwargs )
545561
546562if __name__ == "__main__" :
547563 main (sys .argv [1 :])
0 commit comments