A Tcl Preprocessor, version 0.11 Ken Edwards In Brief -------- Tpp is a slight modification to cpp to allow preprocessing of Tcl/Tk source files. In addition to providing define constructs, tpp allows conditional statements to be included in tcl source files, and strips comments and extraneous white space from tcl sources to yield some speed improvements. Of course this has the *VERY NEGATIVE* side effect of having to preprocess all your source files. One of the neat things about Tcl/Tk is the ease in changing things because of no compile. I find that a simple Makefile suffices, and this runs fast enough to be acceptable to me. For those who do not want to do this, a small hack in Tcl_EvalFile to pipe the source in though tpp will work. I do not use this myself as I have some programs that should work with a standard wish. Changes from version 0.10 ------------------------- * added -P flag to preserve whitespace in processed files * added #%protect and #%unprotect directives to preserve whitespace and defines in protected regions * added -L flag to produce #line directives, now off by default * added example.tcl to illustrate the new options Thanks to saunier@simtoul.fr for suggesting these changes. Why DECUS cpp? -------------- I used decus cpp because it is public domain, available in comp.sources.unix, and small and easy to modify. Well, easier for me 'cause I am better at 'C' than lex and yacc. I looked at GNU cpp, but it looked like you needed the entire gcc source tree and a good understanding of lex and yacc to make it work. If anyone wants to prove me wrong, please upload your modified version. Why not m4? ----------- I guess mostly from mental inertia, ( one of the most powerful forces in the universe ). I am primarily a 'C' or 'Tcl/Tk' programmer, so what I wanted was something that would be easy for me to adapt to, cpp seemed a natural since I already use it all the time. Differences between cpp and tpp ------------------------------- The # char is already in use as the comment char in Tcl/Tk. Therefore tpp uses #% as command prefix. #define in cpp would be #%define in tpp. This has the added benefit that #%define appears as a comment if you run tcl/wish on an unprocessed source file. eg: this will run through wish without modification, int the first case, running wish normally, in the second producing a single processed file from the three source files. #%ifndef XTAL source "$xl_Path(Library)/xl_bind.tk" source "$xl_Path(Library)/xtal/xl_batch.tk" #%else #%include #%include #%endif In 'C' strings are protected by the preprocessor so #defines do substite in them. In Tcl/Tk, you are never sure if you should substitute in a string or not, so tpp substitutes *ALL* occurances of defines, even in quoted strings. This may be dangerous, but if care is taken in choosing uniq names for defined strings, problems should not arise. In version 0.11 there is a -P flag to modify this behaviour. eg: do this #%define XYZZY testing bind Text <1> "puts XYZZY" #line 1 "jj" bind Text <1> "puts testing" eg: dont do this #%define canvas testing canvas .c .c text 0 0 -text "this is a canvas" #line 1 "jj" testing .c .c create text 0 0 -text "this is a testing" Tpp strips white space from ALL lines in the file, this is *good* most of the time, but if you have a formatted string, you will find that it is messed up. eg: puts " Hello World" turns to puts " Hello World" In version 0.11 this behavior can be modified using the -P flag, or by inserting #%protect directives in the source. eg: #%protect puts " Hello World" #%unprotect turns to puts " Hello World" An Example ---------- #% define GIZMO 10 #% define TRUE 1 #% define FALSE 0 set x TRUE set i 1 while { x == TRUE} { incr x if { i == GIZMO } { set x FALSE #%ifdef DEBUG puts "x has been set to FALSE" #%endif } } tpp test.tk > test.t #line 1 "test.tk" set x 1 set i 1 while { x == 1} { incr x if { i == 10 } { set x 0 } } or tpp -DDEBUG test.tk > test.t #line 1 "test.tk" set x 1 set i 1 while { x == 1} { incr x if { i == 10 } { set x 0 puts "x has been set to 0" } } How do I use it? ---------------- Preprocess your source files with tpp, use Make or a tcl script: in tcl: foreach file [glob -nocomplain *.tcl] { set base [file rootname $file] tpp $file > $base.t } auto_mkindex . *.t in Make %.t: %.tk tpp $(TFLAGS) $< > $@ tfiles: xxx.t yyy.t tcl -f rebuild.tcl Where do I get it? ------------------ I have uploaded the current version of the software to harbor.ecn.purdue.edu. Caveat: ------- Works for me, if it doesn't work for you too bad, if it erases your disk, crashes your system, or kills your cat, I am sorry but not responsible. I only use a very small subset of the preprocessor, mostly #%ifdef #%include and #%define, other commands may or may not work. Read the file COPYING for details. Copyright: ---------- Decus cpp is public-domain. Changes are copyright Ken Edwards for no other reason than I like the Berkeley disclaimer. Read the file COPYING for details. Where are the man pages? ------------------------ Sorry, you just read all the documentation available. Read the file cpp.mem, and the differences above.