This is Info file chpp.info, produced by Makeinfo version 1.68 from the input file chpp.texi. This file documents the `chpp' Preprocessor. Copyright (C) 1997-1999, Mark Probst, Heinz Deinhart Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. START-INFO-DIR-ENTRY * chpp:: A very powerful macro preprocessor. END-INFO-DIR-ENTRY  File: chpp.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) * Menu: * Introduction:: Overview * Guided Tour:: A Guided Tour through `chpp' * Examples:: A few examples illustrating `chpp' features * Invoking chpp:: `chpp' command line syntax * Language Reference:: Detailed description of `chpp' syntax and semantics * Extending chpp:: * Special Forms:: * Macro Reference:: Detailed description of all `chpp' macros * Internal Variables:: Detailed description of all internal variables * Package Reference:: Description of all standard `chpp' packages * Macro Index::  File: chpp.info, Node: Introduction, Next: Guided Tour, Prev: Top, Up: Top Introduction ************ `chpp' is a preprocessor. Therefore, its main purpose is to modify input text by including other input files and by macro expansion. Programs performing these tasks already exist, among them the popular C Preprocessor (`cpp') and `m4', which have proven to be convenient and valuable tools suitable for a variety of tasks. The motivation for `chpp' is thus questionable. What distinguishes `chpp' from at least the two programs mentioned above are mainly two features: * `chpp' is non-intrusive. This means that you can take your favourite text and it is very unlikely that it will be changed when piped through `chpp'. Due to this feature it is pretty easy to start using `chpp' since you can just start writing your text and need not concern yourself with `chpp' sitting in the background changing it for no obvious reason. * `chpp' is not just a package for performing simple macro expansion, but can indeed be considered a full-fledged programming language. Most importantly, it provides support for complex data structures, namely lists and hashes (associative arrays), which can be nested arbitrarily. `chpp' consists of two parts which could, in some sense, be regarded as two separate passes over the input file. This is not entirely true, though, since the two parts are intertwined and cannot be separated. The first part, which performs command processing, is similar to what `cpp' does. It allows the inclusion of other files, simple macro definitions and conditional inclusion and exclusion of parts of the input. The second part does macro processing and is the actual workhorse and core of `chpp'. Although macro processing on its own could do anything that can be accomplished with commands, the latter are not only easier to use but also easier to read and therefore improve clarity. * Menu: * The Name:: What `chpp' stands for * Uses:: Uses for `chpp' * Non Uses:: What `chpp' should not be used for * Planned Features:: Planned but not yet implemented features * Obtaining chpp:: How to get `chpp' * History:: The History of `chpp' * Bugs:: Known bugs in `chpp' * Reporting Bugs:: How to report bugs to the authors * Licence:: Licencing terms and warranty of `chpp' * The Authors:: About the authors of `chpp' * Acknowledgements:: We would like to thank...  File: chpp.info, Node: The Name, Next: Uses, Prev: Introduction, Up: Introduction What `chpp' stands for ====================== `chpp' does *not* stand for Chakotay Preprocessor.  File: chpp.info, Node: Uses, Next: Non Uses, Prev: The Name, Up: Introduction Uses for `chpp' =============== `chpp' can be used very well as * a preprocessor for HTML (*note Web Site::.). This was, by the way, our original motivation for `chpp' (*note History::.). * a CGI scripting language. `chpp' will become even more attractive for this kind of application when the planned database interface (*note Planned Features::.) is available. * a generator of Quake(tm) configuration files. * a producer of funny sentences (*note Tautogen::.). * and a lot more...  File: chpp.info, Node: Non Uses, Next: Planned Features, Prev: Uses, Up: Introduction What `chpp' should not be used for ================================== `chpp' should, due to its nature, not be used for * interactive applications. * applications where text output is only a secondary function. * applications which require speed. Unfortunately, `chpp' is not a fast program. However, this may change in the future (*note Planned Features::.).  File: chpp.info, Node: Planned Features, Next: Obtaining chpp, Prev: Non Uses, Up: Introduction Planned but not yet Implemented Features ======================================== We will, in some of the next releases, improve the performance of `chpp' by yet another factor of two for typical applications. It will be possible to write new built-in macros in C, which `chpp' will load dynamically at run-time (*note Extending chpp::.). We would also like to add a few extension packages to `chpp', which will make it more suitable for and easier to apply to various applications, most notably CGI scripting, HTML generation and database interfacing.  File: chpp.info, Node: Obtaining chpp, Next: History, Prev: Planned Features, Up: Introduction Obtaining `chpp' ================ `chpp' is available for free download on the world-wide-web. Point your web-browser at `http://chakotay.ml.org/' (or `http://chakotay.ml.org/chpp/' if you are using an ancient browser). From there you can download the latest version of `chpp'.  File: chpp.info, Node: History, Next: Bugs, Prev: Obtaining chpp, Up: Introduction The History of `chpp' ===================== Not much here, yet.  File: chpp.info, Node: Bugs, Next: Reporting Bugs, Prev: History, Up: Introduction Problems and Known Bugs ======================= `chpp' is far from error-free in its current version. It works quite reliably now when not stressed too far, though. The biggest problem is currently that `chpp''s error handling is insufficient. `chpp' does not report some errors, while others cause it to crash or to hang up in an endless loop. We do, of course, plan to change this in the future.  File: chpp.info, Node: Reporting Bugs, Next: Licence, Prev: Bugs, Up: Introduction Reporting Bugs ============== Before you tell us about a bug, please check that you are using the latest version of `chpp' (*note Obtaining chpp::.). If this is not the case, please upgrade and try again. Please do not report bugs that concern `chpp''s error handling. We know that it is unreliable and buggy and we will change that. You should, however, report any incident where `chpp' does anything wrong with a script which you believe is correct. In such a case, please write us an email containing the script that causes `chpp' to fail and any additional files that your script needs. Better yet, try to narrow down the bug to the smallest script possible. Do also include information on the configuration you ran `chpp' on, especially if the bug only happens to show up with this configuration. The email address you should send your bug-report to is .  File: chpp.info, Node: Licence, Next: The Authors, Prev: Reporting Bugs, Up: Introduction Licence and Warranty ==================== `chpp' is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. `chpp' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with `chpp'; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  File: chpp.info, Node: The Authors, Next: Acknowledgements, Prev: Licence, Up: Introduction The Authors =========== `chpp' was designed and implemented by Heinz Deinhart () and Mark Probst (). Check out the `chpp' homepage (*note Obtaining chpp::.) for more information.  File: chpp.info, Node: Acknowledgements, Prev: The Authors, Up: Introduction Acknowledgements ================ Our thanks go to Tatjana Svizensky for proofreading (an older edition of) this manual and to Herbert P"otzl for donating the hash-table functions, which we were too lazy, erm, too busy to implement, and for not reading the examples chapter of this document.  File: chpp.info, Node: Guided Tour, Next: Examples, Prev: Introduction, Up: Top A Guided Tour through `chpp' ****************************  File: chpp.info, Node: Examples, Next: Invoking chpp, Prev: Guided Tour, Up: Top Examples ******** This chapter gives a few more practical examples of the use of `chpp', illustrating a few of its many possible applications. * Menu: * Song Lyrics:: * Web Site:: * Tautogen::  File: chpp.info, Node: Song Lyrics, Next: Web Site, Prev: Examples, Up: Examples Song Lyrics =========== Let us assume you have gathered a collection of song lyrics by various performers as text files. You wish to generate not only HTML files for all the songs but also an index page for each performer which contains, sorted by album, hyperlinks to all the song HTML files. The song files you have collected all look like this: Gloria I try to sing this song. I try to stand up. But I can't find my feet. I try, I try to speak up. But only in you I'm complete. ... Furthermore, assume you have created a directory for each performer containing a directory for each album where the song files reside. The names of the directories not necessarily match the corresponding performer's name or the album's, as these often contain spaces, which are uncommon in file names. The same applies to the song file names. Thus, our first task is to somehow associate the names of the performers, albums and songs with the song files. We have a bonus for the song names since these are included in the song files themselves (in the first line). For simplicity we will include this information in the files themselves, namely as HTML comments containing assignments in `chpp' syntax. To modify the files, we will use the following `chpp' script: #include files.chh %\ %\ %frest(%file)\ %fclose(%file)\ The variables `SONGFILENAME', `ALBUM' and `PERF' must be set via the command-line. We can now convert all files in one album with the following shell-command (assuming we are in the correct directory and that all song files have the extension `.txt'): $ pwd /home/schani/lyrics/u2/october $ for fn in *.txt ; do > chpp -DSONGFILENAME=$fn -DALBUM='October' \ > -DPERF='U2' ../../convert.ch >../$fn > done Note that we have generated the modified files in the performer's directory. After we have done this for all albums, we can delete the album directories. The song files now look like this: I try to sing this song. I try to stand up. But I can't find my feet. I try, I try to speak up. But only in you I'm complete. ... We will now generate HTML files for the songs. For simplicity, we will generate a simple HTML file which contains the song text in a `
' block:

     #include files.chh
     %%void(%{%fgets(%file)})\
     \
      
     %song - %album - %perf
      
     

%song

     %frest(%file)\
     
%fclose(file)\ Since the information about the song title, album and performer is coded as `chpp' code in the first line, we can obtain it by just evaluating it and ignoring its result. With this script we can now generate HTML files for all songs of one performer with the following `bash' command: $ pwd /home/schani/lyrics/u2 $ for fn in *.txt ; do > chpp -DSONGFILENAME=$fn ../template.ch >${fn%.txt}.html > done Finally, we need to generate an index file for each performer containing hyperlinks to all songs. This file is generated by the following `chpp' script: #include files.chh %\ %\ %foreach(songfilename,%ssplit(%'[ \n]+',%sremovews(%frest(file))), %\ %void(%{%fgets(%songfile)})\ %fclose(%songfile)\ %%void(%smatch(%'(.*)\\.',%songfilename,%®s))\ %\ %if(%hcontains(%albums,%album), % , % )\ )\ %fclose(file)\ \ %perf

%perf

%foreach(album,%lsort(%hkeys(%albums)),\

%album

%'\n'
%'\n'\ %foreach(song,%lsort(%hkeys(%albums{%album})),\

%song%'\n'\ )\

%'\n'\ )\ The first part of the file gets all information about the songs in the current directory. It generates an entry in the hash `%albums' for each album, which in turn is a hash containing all names of the HTML files indexed by the song names. The second part just iterates through this table, producing an `

' for each album and an anchor for each song within.  File: chpp.info, Node: Web Site, Next: Tautogen, Prev: Song Lyrics, Up: Examples Web Site ======== Suppose you were to create a web-site with three main pages: News, Tips and Tricks. Each of these pages should have a layout similar to this: N N EEEE W W SSS News NN N E W W S N N N EEE W W W SSS _Tips_ N NN E W W W S N N EEEE W W SSS _Tricks_ -------------------------------------------- This is good news! -------------------------------------------- News | _Tips_ | _Tricks_ The header consists of a big graphic banner denoting the title of this particular page. On the right side of the banner are three little graphics, each standing for one of the pages. Two of them lead to the other two pages, whereas the one for the actual page is not functional and grayed out. The footer consists of a textual link bar with two active links and one 'inactive link' (normal text) for the actual page. Although these three pages are easy to implement with conventional methods, this becomes increasingly difficult when there are more pages or even hierarchical structures of pages. Therefore, we will use this as an example of how to easily create HTML pages with `chpp', leaving more sophisticated designs to the gentle reader. Ideally, we would like, say, the news source file (which we name `news.csml'), as rendered above, to look like this: #include header.chml This is good news! #include footer.chml This way, we need not be concerned with the design of the header and footer when we work on the pages and we can easily modify the header and footer in one central place, although they apply to our whole web-site. Now we need a place where we can enter all the names of the main pages of our web-site and associate them with their corresponding files. We call this file `menu.chml': %addmenuentry(News,news.csml) %addmenuentry(Tips,tips.csml) %addmenuentry(Tricks,tricks.csml) We simply assume that the generated HTML files will have the same base-name as the sources but the extension `.html'. We furthermore assume that for each main-page we have three additional graphics available, namely one containing the large banner and two containing the small icons, where one of the two is grayed out. These images have the format JPEG, hence the extension `.jpg'. Their base-names consist of the base-names of their main-pages followed by one of the suffixes `_l', `_s' and `_s_g', where `l' denotes large, `s' small and `g' gray. The include-file `header.chml' fulfills two purposes: Firstly, it must process the information of the file `menu.chml' and secondly, it must generate the header of the HTML file. Since the latter depends on the former, we will first focus our attention on processing the information of `menu.chml'. Each main page will be represented by a hash containing the keys `filename', `name', `htmlfilename', `imglarge', `imgsmall' and `imgsmallgray', the meanings of which should be obvious. We will collect all these hashes in a list named `menu', which will contain these hashes in the order in which they were entered in `menu.chml'. Since `menu.chml' is already in `chpp' syntax, all we need to do is to define a macro `addmenuentry' which creates such a hash and appends it to the list `menu': %\ %define(addmenuentry,name,filename, %%void(%smatch(%'(.*)\\.csml$',%filename,%®s))\ %\ %lappend(%&menu, %hash(filename,%filename, name,%name, htmlfilename,%basename.html, imglarge,%_l.jpg, imgsmall,%_s.jpg, imgsmallgray,%_s_g.jpg)) )\ Now we can include `menu.chml' for its side-effects: %void( #include menu.chml )\ Finally, for convenience, we define a variable `thisentry' which contains the hash that applies to the currently processed page: %\ Now we are set and can generate the header of the HTML file: %thisentry{name}
%thisentry{name} #include choicestrip.chml

The file `choicestrip.chml' generates a vertical table consisting of the small images for the main-pages with links. It is quite simple: %foreach(menuentry,%menu,
\ %if(%equal(%menuentry{filename},%thisentry{filename}), %menuentry{name} , \ %menuentry{name}\ ) )
The footer is even more simple: It contains a horizontal rule and a choice-bar:
#include choicebar.chml `choicebar.chml' is similar to `choicestrip.chml': #include list.chh
%\ %foreach(menuentry,%menu, %lappend(%&barentries, %if(%equal(%menuentry{filename},%thisentry{filename}), %menuentry{name} , %menuentry{name} ) ) )\ %listJoin(%' | ',%barentries)
All we need now is a comfortable way to create all HTML files from the sources. That is what makefiles are for. They have the additional advantage that files are regenerated only if needed, i.e. when one of the files that the file to be created depends on has changed. A makefile for `gnumake' suitable for our simple purposes would look like this: CHFILES=header.chml footer.chml choicebar.chml choicestrip.chml all : news.html tips.html tricks.html %.html : %.csml ../../macros -o $ $< news.html tricks.html tips.html : $(CHFILES) clean : rm -f news.html tips.html tricks.html  File: chpp.info, Node: Tautogen, Prev: Web Site, Up: Examples Tautogen ======== Suppose we have a simple context-sensitive grammar, which we want to use to generate sentences, which is quite the opposite of parsing sentences of that grammar. To illustrate this more clearly, let us assume we have a file like this: --sentence $subject $verb $object. $subject, while $gerund $object, $verb $object. $subject watches $object $gerund $object. --subject $person The $adjective $person --object $person --person Butthead Mrs Krabappel Charlie Brown Mrs Robinson --adjective observant naive embarassed --verb kisses kicks envies --gerund holding zapping hugging smashing The file is separated into several categories containing so-called productions for so-called non-terminals. The first non-terminal is called the start non-terminal, which is, in our case, `sentence'. We start by randomly picking one of the right-hand-sides of the productions of the start non-terminal (i.e. one of the lines following the introduction of `sentence'). Now we repeat the following cycle until our string contains no more placeholders (words prefixed by the dollar sign (`$')): Replace the first placeholder by the right-hand-side of a randomly picked production for that placeholder. The process could evolve like this: $sentence $subject, while $gerund $object, $verb $object. The $adjective $person, while $gerund $object, $verb $object. The naive $person, while $gerund $object, $verb $object. The naive Charlie Brown, while $gerund $object, $verb $object. The naive Charlie Brown, while hugging $object, $verb $object. The naive Charlie Brown, while hugging $person, $verb $object. The naive Charlie Brown, while hugging Mrs Robinson, $verb $object. The naive Charlie Brown, while hugging Mrs Robinson, kicks $object. The naive Charlie Brown, while hugging Mrs Robinson, kicks $person. The naive Charlie Brown, while hugging Mrs Robinson, kicks Butthead. It is easy to see that this simple algorithm even allows for recursive grammars. This example is not a typical application for a pre-processor. It should rather demonstrate that `chpp' can be used very successfully for tackling problems not within its direct field of application, i.e. that it is suitable for more general problems. You may have noticed that our grammar file is not in `chpp' syntax, so we have the choice of either converting it or parsing it at run-time. Since the former has the disadvantage of being more complicated in usage (the grammar would have to be converted each time it is changed) and is not easier to implement than the latter, the choice is obvious. The first step of our application is reading in the grammar file, which we call `grammar'. Its content will be stored in a hash `data', where the keys are the names of the non-terminals and the values are the lists of the right-hand-sides of the corresponding productions. %\ %\ %\ %until(%feof(%file), %\ %\ %if(%[%smatch(%'^--([a-zA-Z0-9_]+)',%line,%®s)!=-1], %\ %\ %if(%not(%bound(start)),%) , %if(%line,%) ) )\ %fclose(%file)\ We then proceed to define some variables and macros. First, if the variable `n', which will denote the number of sentences generated, is not defined (it could be defined on the command-line), it is set to `10': %if(%not(%bound(n)),%)\ The macro `some', when called with the name of a non-terminal, returns the right-hand-side of a random production for that non-terminal: %define(some,nt,%data{%nt}[%random(%llength(%data{%nt}))])\ The generation of the sentences is now a fairly trivial task: #include strings.chh %for(i,1,%n, %\ %\ %while(%%[mp!=-1], % )\ %current%'\n\n' )\  File: chpp.info, Node: Invoking chpp, Next: Language Reference, Prev: Examples, Up: Top Invoking `chpp' *************** To get a quick overview of `chpp' command line syntax, just type chpp --help The general `chpp' syntax is chpp [OPTION ...] [FILENAME ...] `chpp' reads and processes all specified files in sequential order, as if they were one file. If no file is specified, `chpp' reads from standard input. Output is written to standard output if not otherwise specified. The following is a summary and description of all available `chpp' options: `--version' Prints out the version number of the invoked `chpp'. `--help' Prints out a summary of `chpp' command line syntax. `--output FILENAME' `-o FILENAME' Specifies that output should be written to file FILENAME. `--include-dir DIR' `-I DIR' Adds DIR to the list of standard include directories. `-D NAME=VALUE' Defines the `chpp' variable NAME with the value VALUE. `--generate-dependencies' `-M' Generates a dependency list suitable for `make' like `cpp'.  File: chpp.info, Node: Language Reference, Next: Extending chpp, Prev: Invoking chpp, Up: Top Language Reference ****************** Files processed with `chpp' are passed through two stages, which are, however, not sequential in nature but can rather be viewed as coroutines. The first stage processes commands (*note Commands::.). Command processing is a sequential process, i.e. no loops or recursions occur. The second stage is macro processing (*note The Meta-Char::.) and allows for loops as well as for recursion. * Menu: * Commands:: * The Meta-Char:: * Data Types:: * Variables:: * Arithmetic Expansion:: * Quotation:: * Explicit Evaluation::  File: chpp.info, Node: Commands, Next: The Meta-Char, Prev: Language Reference, Up: Language Reference Commands ======== Command processing is line-oriented. It affects only lines which have, as their first non-whitespace character, the command-char (`#'). All other lines are passed through literally. Another function of command processing is the concatenation of lines: If the last character of a line is the backslash (`\'), then the backslash, the following newline and all leading whitespace of the next line are ignored. A line invoking a command consists of optional whitespace at the beginning, the command-char `#', optional whitespace, the command name, whitespace and the command arguments (if any). Thus, the following lines are all commands (given that the command names exist): #abc #def arg # ghi too many arguments while the following lines are not: this is a line without commands. although this line contains a # it is not a command. * Menu: * Comments:: * Command Reference::  File: chpp.info, Node: Comments, Next: Command Reference, Prev: Commands, Up: Commands Comments -------- The command `!' (exclamation mark) is a special case among commands, as it does nothing, independent of its parameters, i.e. can be used to write comments, or, if used in the first line of a file, to specify the command line to be used if the containing file is executed. Thus, this is a "Hello world" program in `chpp': #! /usr/local/bin/chpp Hello world! After setting the executable bit for this file, it can be called like any command and will produce the output Hello world! Note that the exclamation mark must be followed by whitespace.  File: chpp.info, Node: Command Reference, Prev: Comments, Up: Commands Command Reference ----------------- - Command: include FILENAME Includes the file FILENAME. If FILENAME is relative, it is first searched for in the directory of the including file, then in the directories contained in the include search path (*note Invoking chpp::.). If the file is not found, an error message is produced. - Command: define NAME VALUE Defines the global variable NAME to contain whatever VALUE evaluates to. - Command: if CONDITION Evaluates CONDITION. If its boolean value is FALSE, it skips everything up to the corresponding `end'. - Command: ifdefined SYMBOL - Command: ifdef SYMBOL If a variable with the name SYMBOL does not exist, skips everything up to the corresponding `end'. - Command: ifnotdefined SYMBOL - Command: ifndef SYMBOL If a variable with the name SYMBOL exists, skips everything up to the corresponding `end'. - Command: error MESSAGE Produces an error message with the text MESSAGE. - Command: discard - Command: disc Discards everything up to the corresponding `end'.  File: chpp.info, Node: The Meta-Char, Next: Data Types, Prev: Commands, Up: Language Reference The Meta-Char ============= The second stage processes everything that is passed through by the first stage. It is called macro processing because its main use is the expansion of macros. There is just one special character for this stage, namely the meta-char (`%'). Only character sequences beginning with the meta-char are modified by the macro processing stage. All other characters are simply passed through. Since `chpp' was designed to be non-intrusive, even uses of the meta-char which do not correspond to the uses described in this chapter are copied verbatim. For example: Temperature today is 10% above average. => Temperature today is 10% above average. In cases where it is absolutely necessary that the meta-char not be interpreted as special, it can be quoted with itself (i.e. `%%'), yielding one meta-char. Example: %\ %%heinz evals to %heinz. => %heinz evals to deinz.  File: chpp.info, Node: Data Types, Next: Variables, Prev: The Meta-Char, Up: Language Reference Data Types ========== The only primitive type in `chpp' is the string. Values of that type are referred to as scalars (*note Scalars::.). Values of any type can be combined arbitrarily to lists (*note Lists::.) and hashes (*note Hashes::.). Closures (*note Closures::.) also form a data type as they can be stored and used, even though they cannot be directly manipulated. * Menu: * Scalars:: * Lists:: * Hashes:: * Closures::  File: chpp.info, Node: Scalars, Next: Lists, Prev: Data Types, Up: Data Types Scalars ------- Scalars are strings of arbitrary length (including the length 0).  File: chpp.info, Node: Lists, Next: Hashes, Prev: Scalars, Up: Data Types Lists ----- Lists are ordered collections of arbitrary values indexed by consecutive numbers starting at 0. It follows that lists cannot have gaps.  File: chpp.info, Node: Hashes, Next: Closures, Prev: Lists, Up: Data Types Hashes ------ Hashes are ordered collections of arbitrary values indexed by arbitrary scalars, i.e. they establish a so-called key/value mapping.  File: chpp.info, Node: Closures, Prev: Hashes, Up: Data Types Closures -------- A closure is a piece of code associated with an environment in which it is to be executed, as created by `lambda' (or `define', for that matter). Thus, the names macro and closure actually stand for the same thing, although one usually tends to call anonymous macros (i.e. values returned by `lambda') closures, whereas named closure (i.e. `define'd macros) are usually called macros.  File: chpp.info, Node: Variables, Next: Arithmetic Expansion, Prev: Data Types, Up: Language Reference Variables ========= In order to be able to retain values for subsequent use it is necessary to store them in variables. * Menu: * Accessing Variables:: * Subscription:: * Copies and References:: * Macro Invocation:: * Subscribing Non-Variables:: * Assignment:: * Scoping::  File: chpp.info, Node: Accessing Variables, Next: Subscription, Prev: Variables, Up: Variables Accessing Variables ------------------- There are two different syntactic forms of variable access, called the short and the long form. The short form consists of the meta-char followed by an optional ampersand (`&') followed by the variable name, e.g. `%name' or `%&name'. The variable name is taken as-is, i.e. is not evaluated. The variable name ends with the first char that is not a letter, a digit or the underscore (`_'). If a variable with the given name does not exist, the whole string is not interpreted as a variable access and is copied verbatim, i.e. `%name' evaluates to `%name' if there is no variable with the name `name'. The long form consists of the meta-char followed by the optional ampersand and the variable name within angle brackets, e.g. `%' or `%<&name>'. The variable name is evaluated before the variable is looked up, making it possible, for example, to use variable names containing right angle brackets: The term `%<%'>>>'>' accesses the variable `>>>'. If a variable with the name does not exists, an error message is issued. *Note:* Although it is possible to use macros to construct variable names (e.g. `%<%name>'), this feature is deprecated. Please don't use it.  File: chpp.info, Node: Subscription, Next: Copies and References, Prev: Accessing Variables, Up: Variables List and Hash Subscription -------------------------- If the variable is a list or a hash, it can be subscribed by appending the index in brackets or curly braces to the name, in both the short and the long form. In order to access nested data structures, any number of such indexes can be used in one access, for example `%name[3]{foo}'.  File: chpp.info, Node: Copies and References, Next: Macro Invocation, Prev: Subscription, Up: Variables Copies and References --------------------- Accessing a variable or a subscript without an ampersand produces a shallow copy of its value, i.e. accessing a list produces a copy of the list containing the elements of the original list. Example: %%\ %same(%&lst1,%&lst2) : %same(%&lst1[0],%&lst2[0]) => 0 : 1 Accessing a variable or subscript with an ampersand produces the same value, i.e. can be used to bind two names to the same value: %%\ %same(%&str1,%&str2) => 1 There are several important issues to this: * Copying values is of course slower than just reusing the same value. `chpp''s built-in macros, however, are wise enough not to copy their arguments when they don't need to. For example, calling `llength' never copies its argument. * Circular data structures can be built easily. Care has to be taken when processing these structures, or one might end up in an endless loop. * Memory management becomes more complicated when arbitrary cross-references in data-structures are allowed. This, however, need not concern the `chpp' user, as it employs garbage collection to free unused memory.  File: chpp.info, Node: Macro Invocation, Next: Subscribing Non-Variables, Prev: Copies and References, Up: Variables Macro Invocation ---------------- A macro can be invoked by appending, in the short or long form of variable access, to the variable name or subscript a left parenthesis followed by the actual arguments separated by commas followed by a right parenthesis, e.g. `%list(a,b)'. The value that is yielded by the macro invocation cannot be subscribed further, i.e. `%list(a,b)[1]' is not allowed. However, see *Note Subscribing Non-Variables:: for a method to achieve this goal. Arguments of a macro-call are processed as follows: First, all leading and trailing whitespace from all arguments is removed. Then, the remaining strings are evaluated and the results are passed as arguments to the macro. In order to pass an argument with leading or trailing whitespace to a macro, it must be quoted. For example: %define(foobar,arg,"%arg") %foobar( xyz ) => "xyz" %foobar( ) => "" %foobar( %' ' ) => " " %foobar(%' xyz ') => " xyz "  File: chpp.info, Node: Subscribing Non-Variables, Next: Assignment, Prev: Macro Invocation, Up: Variables Subscribing Non-Variables ------------------------- It is possible to subscribe values that are not variables, for example ones that are returned from macros, by using a modified long form of variable access. Instead of the variable name the expression yielding the value enclosed in parentheses is used. Upon evaluation, the expression is evaluated and all following subscriptions are applied to its value. Example: %<(%list(a,b))[1]> => b  File: chpp.info, Node: Assignment, Next: Scoping, Prev: Subscribing Non-Variables, Up: Variables Assignment ---------- Assignment syntax is an enhancement of the long form of variable access. The last subscription (or the variable name, if no subscription is used) is followed by an equal sign (`=') which is followed by an expression yielding the value to be assigned. When assignment is attempted to an element of a list which is out of bounds, the list is enlarged. Elements between the formerly last element and the newly added element default to the empty string. Indexes less then 0 are not allowed. Assigning to a key in a hash which is not part of it, adds the key/value pair to the hash. It is not possible to assign to a subscript of a value which is not subscribeable, i.e. it is not possible to do `%' if `bar' is not a list. To make `bar' an empty list, simply do `%'. Assignment usually changes a binding, be it in an environment or in a list or hash. This means that the sequence %% first binds the name `value' to a newly created list and then rebinds `value' to a newly created hash, leaving the old list intact. When using the ampersand-form, however, the old value is changed to the new value, which is a destructive process. Example: %%%<&value=123>%ref => 123 When an assignment to a variable is executed for which there is no binding, a new binding in the global environment is created for this variable name.  File: chpp.info, Node: Scoping, Prev: Assignment, Up: Variables Scoping Rules ------------- `chpp' uses lexical scoping, using an environmental model, very similar to Scheme's. An environment contains bindings for names to values and a reference to its parent environment. The only environment without parent is the global environment. Execution always takes place in some environment. If a variable name has to be resolved, the current environment is checked for whether it contains a binding for that name. If it does not, its parent is checked, and so on until the global environment is reached. If it does not contain a corresponding binding, the variable name cannot be resolved and an error message is produced. New environments are created upon several occasions: * The execution of `locals' and `let' expressions (*note Special Forms::.). The new environment is set up to contain bindings for all the variables mentioned as parameters to `locals' or `let'. The parent environment of the new environment is the environment active at the time of execution of the expression. The environment is active throughout the body of the expression. * The execution of a closure (i.e. the value returned by an invocation of `lambda' or the value bound to a name as a result of an invocation of `define'). The environment is set up to contain bindings for all the parameters of the closure. The parent environment of this new environment is the environment active at the time of the generation of the closure, i.e. of the invocation of `lambda'. That makes it possible to do things like this: %define(newcounter,%let(c,0,%lambda(%%c)))\ %\ %counter() %counter() %counter() => 1 2 3 The parent environment for the environments of the closure invocations is the environment created by `let', mapping `c' to `0', which is itself created every time `newcounter' is executed. Thus, in a way, `counter' carries a state, namely its private variable `c'. Had we called `newcounter' a second time, a second counter would have been created, with its own `c', initally set to `0', completely independent of the first. * The execution of `for', `foreach' and `foreachkey' expressions (*note Special Forms::.).  File: chpp.info, Node: Arithmetic Expansion, Next: Quotation, Prev: Variables, Up: Language Reference Arithmetic Expansion ==================== `chpp' permits the evaluation of arithmetic expressions by enclosing the expression in square brackets (`[]') preceded by the meta-char. The expression is first evaluated according to `chpp' rules and the resulting value is treated as an arithmetic expression which, in turn, yields a number. Whitespace between operators and operands is ignored. The following table is a summary of all available operators together with their arity. They are sorted by precedence, the first line being of the highest precedence. All binary operators evaluate from left to right. All operators have the same meaning as the corresponding operators in the C language. *Operators* *Arity* `!', `~', `-' unary `*', `/', `%' binary `+', `-' binary `<', `>', binary `<=', `>=' `==', `!=' binary `&' binary `^' binary `|' binary `&&' binary `||' binary Precedence of operators can be overridden by using parentheses (`()'). In order to make arithmetic expressions more readable, it is allowed to refer to the values of variables within an arithmetic expression by writing its name--without a preceding meta-char. Note that subscription and macro invocation using this syntax is not allowed. Some examples: %[1+2] => 3 %[1.5+3.3] => 4.800000 %[3==3] => 1 %[3!=3] => 0 %[(1+2)*(3+4)] => 21 %%[%x+1] => 5 %%[x+1] => 5  File: chpp.info, Node: Quotation, Next: Explicit Evaluation, Prev: Arithmetic Expansion, Up: Language Reference Quotation ========= To prevent some string from evaluation, it can be quoted by enclosing it in a pair of single-quotes (`'''), preceded by the meta-char. The only special characters after the first double-quote are the quote-char (the backslash, `\') and the closing double-quote. The quote-char gives special meanings to some characters following it: an `n' becomes a newline character and a `t' is interpreted as a tabulator. All other character preceded by the quote-char stand for themselves. This includes the quote-char and the double-quote, i.e. `%'\\\''' evaluates to `\''.  File: chpp.info, Node: Explicit Evaluation, Prev: Quotation, Up: Language Reference Explicit Evaluation =================== In order to evaluate a string twice, for example to evaluate the contents of a variable, the string must be enclosed in curly braces (`{}'), preceded by the meta-char. Example: %%%{%b} => abc  File: chpp.info, Node: Extending chpp, Next: Special Forms, Prev: Language Reference, Up: Top Extending `chpp' ****************