A template-specific preprocessor symbol is defined in a template file like:
'::SYMBOL::tag [<optional value>]'
Note that the SYMBOL (the name) will be lower-cased for use. The above would be seen as \#symbol:tag# in a template where used.
The preprocessor symbol values can themselves contain \#<symbol># constructions, allowing you to use dynamic values inside the file-only values, to target external behavior (Changing the filename, as an example usecase).
Also, preprocessing can include other files, and these other files may provide "template-specific" variables, even though they are not defined directly in the template.
No attempt is made to find circular references. If \#<symA># refers to \#<symB>#, and the inclusion path eventually tries to include \#<symA># again, the result is undefined. A deep-recursion, or out-of-memory crash are the most likely results.