• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

HISTORYH A D19-Jun-19992.5 KiB7972

MakefileH A D03-May-20221.5 KiB5321

Makefile.linuxH A D18-Jun-19991.7 KiB6027

NNLH A D02-Jun-199915.1 KiB324243

READMEH A D18-Jun-199972.9 KiB2,0961,496

gcl.cH A D19-Jun-1999188.7 KiB7,3196,257

gcl.hH A D18-Jun-19999.6 KiB497366

gcldefaults.cH A D02-Jun-1999856 281

gcldefaults.hH A D07-Jun-19993.3 KiB11993

gd.cH A D02-Jun-199959.5 KiB2,6332,113

gd.hH A D02-Jun-19995.4 KiB14888

mtables.cH A D02-Jun-19996.1 KiB727726

sec2000.cH A D02-Jun-19991.9 KiB6912

README

1This is the README file for gracula v3.0, the compiler/interpreter for
2Graphic Counter Language.
3
4Copyright 1999 G. Adam Stanislav
5All rights reserved
6
7The code for gracula consists of the following source files:
8
9gcl.c
10gcl.h
11gcdefaults.c
12gcldefaults.h
13
14The code for a sample GCL application, sec2000, is in the file sec2000.c.
15But see below how you can achieve the same result in plain GCL!
16
17These files are Copyright (c) 1999 G. Adam Stanislav. All rights reserved.
18
19Additionally, several files from Thomas Boutell's gd1.3 packages are
20included, with some modifications to work better with gracula. These files
21are:
22
23gd.c
24gd.h
25mtables.c
26
27The following notice applies to these three files only:
28
29     Portions copyright 1994, 1995, 1996, 1997, 1998, by Cold Spring
30     Harbor Laboratory. Funded under Grant P41-RR02188 by the National
31     Institutes of Health.
32
33     Portions copyright 1996, 1997, 1998, by Boutell.Com, Inc.
34
35     GIF decompression code copyright 1990, 1991, 1993, by David Koblas
36     (koblas@netcom.com).
37
38     Non-LZW-based GIF compression code copyright 1998, by Hutchison
39     Avenue Software Corporation (http://www.hasc.com/, info@hasc.com).
40
41     Permission has been granted to copy and distribute gd in any
42     context, including a commercial application, provided that this
43     notice is present in user-accessible supporting documentation.
44
45     This does not affect your ownership of the derived work itself, and
46     the intent is to assure proper credit for the authors of gd, not to
47     interfere with your productive use of gd. If you have questions,
48     ask. "Derived works" includes all programs that utilize the
49     library. Credit must be given in user-accessible documentation.
50
51     Permission to use, copy, modify, and distribute this software and
52     its documentation for any purpose and without fee is hereby
53     granted, provided that the above copyright notice appear in all
54     copies and that both that copyright notice and this permission
55     notice appear in supporting documentation. This software is
56     provided "as is" without express or implied warranty.
57
58End of gd1.3 notice.
59
60Except for the three files from gd1.3, this package is distributed under
61the terms of the WHIZ KID TECHNOMAGIC NO-NONSENSE LICENCE. Please read
62the file NNL for details. No ammendment has been specified.
63
64The name of the executable program has been changed starting with v2.20
65from gcl to gracula. This happened for two reasons:
66
67        1. GNU Common Lisp is also distributed as gcl. So, a conflict is
68           possible on systems that contain both programs.
69
70        2. To allow for a clear distinction between GCL, the language, and
71           gracula the compiler/interpreter for the language.
72
73Secondly, versions prior to 2.20 suggested the installation of the program
74in /usr/bin. Starting with v2.20, the program is installed to /usr/local/bin
75by default. As of v2.30, the suggested location for graphic files is in the
76/usr/local/share/gracula/pix directory.
77
78If you have many existing counters that expect the program to be /usr/bin/gcl,
79you can create a symbolic link, for example:
80
81        ln -fs /usr/local/bin/gracula /usr/bin/gcl
82
83You can also convert your existing counters to look for /usr/local/bin/gracula
84in the future by entering the following command from your Unix command line:
85
86        echo "#!/usr/local/bin/gracula" >> mycounter.gcl
87
88You need to substitute the name of your counter for "mycounter.gcl". Also, if
89your counter passes command line parameters from the #! line, you need to
90enter those.
91
92For example, if your existing counter uses "#%/usr/bin/gcl -tmaz", enter:
93
94        echo "#!/usr/local/bin/gracula -tmaz" >> mycounter.gcl
95
96Please remember to use the DOUBLE >>, not the single > (which would overwrite
97your counter instead of appending to it).
98
99COMPILATION AND INSTALLATION
100============================
101
102* Under FreeBSD
103  -------------
104
105Gracula is in the graphics category of the FreeBSD ports collection. All you
106have to do is type at the shell prompt:
107
108	cd /usr/ports/graphics/gracula
109	make install
110
111To upgrade from a previous version, first make sure your ports collection is
112up to date. Then type:
113
114	cd /usr/ports/graphics/gracula
115	make clean install -DFORCE_PKG_REGISTER
116
117* Under other systems
118  -------------------
119
120To compile the source code, simply type
121
122        make
123
124To install the compiled software, type
125
126        make install
127
128If you wish to create the symbolic link mentioned above, type:
129
130        make gcl
131
132You can always find the latest version of gracula at:
133
134        ftp.whizkidtech.net/gcl/
135        www.whizkidtech.net/gcl/
136
137INFORMATION
138===========
139
140You can also find an introductory tutorial, FAQ, and other pertinent
141information at www.whizkidtech.net/gcl/.
142
143You can find interesting scripts and counter art in Count Gracula's Gallery,
144located at http://www.whizkidtech.net/gcl/gallery/.
145
146A mailing list for gracula users exists. You can subscribe to it at:
147
148        www.onelist.com/subscribe/gracula
149
150This is highly recommended for several reasons:
151
152        - announcements of new versions will go on the list first;
153        - GCL documentation generally lags behind gracula capabilities,
154          so the list is a perfect place for the how-do-I-do-this type
155          of questions;
156        - others may come up with ideas I have not thought of.
157
158LANGUAGE OVERVIEW
159=================
160
161Graphic Counter Language consists of a set of keywords. It also understands
162compiler directives, and allows for comments. Note that this overview is NOT
163exhaustive. Please visit http://www.whizkidtech.net/gcl/ and read the FAQ and
164the introductory tutorial. Alas, even those are not exhaustive because I spend
165more time updating the software than its documentation... You can always
166subscribe to the mailing list, and ask questions there. Or, you can read
167its archives even if you do not subscribe. See the INFORMATION section above
168for details.
169
170I should probably write a book on GCL. This would force me to take enough time
171to write complete documentation.
172
173Comments and most compiler directives start with an octothorp (`#'). No compiler
174directive starts with two of them, so it is a good idea to start comments with
175a double octothorp (`##'). That way you can be sure that a new version of GCL
176(and gracula) will not interpret an old comment as a new compiler directive.
177
178* The `#!' directive
179  ------------------
180
181Strictly speaking, this is not a GCL directive but a shell directive. Most Unix
182shells understand it to execute the appropriate language interpreter providing
183the file starts with this directive.
184
185For example, suppose a script named counter.gcl starts with the following line:
186
187#!/usr/local/bin/gracula -maz
188
189Now, suppose you enter the following command at your shell prompt:
190
191	./counter.gcl -ld
192
193The shell will examine the start of the file, and find the #! directive. It
194will then interpret your command as if you have typed:
195
196	/usr/local/bin/gracula -maz ./counter.gcl -ld
197
198That means, among other things, that you can incorporate command line switches
199directly into your script, but you can still override them on the command line.
200
201* The image directives
202  --------------------
203
204The `G' in `GCL' stands for `graphic'. It is possible to build a version of
205gracula with all graphics built in (we will talk about that later), but in
206many cases you may want to prefer to use the image directives, as they offer
207the flexibility of using different images in different counters and timers.
208
209Gracula can take image data from four sources:
210
211	- Built-in images;
212	- Individual image files;
213	- Files in a directory;
214	- Image array.
215
216You can use any combination of the four sources in your script.
217
218Gracula understands 23 image directives to determine where the image should
219come from. If none is given, it will use the built-in images. By default,
220the built-in images are null, i.e., no images are built in, unless you build
221them in yourself.
222
223Secondly, if an image is not specified, but an image directory is, gracula
224will use a file with a default name from that directory. The default names
225are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, dash, colon, time, zone, minus, plus, comma,
226head, tail, bkg, tile, and array. Each has the extension of gif, gd, or xbm,
227as appropriate.
228
229The directives are `#0' - `#9' for the images of digits 0-9, `#-' for the
230image of the dash, `#%' for the colon, `#^' for time, `#@' for zone, `#<' for
231minus, `#>' for plus, `#,' for comma, `#~' for space, `#;' for dot, `#:' for
232head, `#.' for tail, `#$' for background, `#+' for tile, `#[' for image array
233file, and `[/' for the image directory described in the previous paragraph.
234Note that the quotes are not part of the directive.
235
236Some things worth noticing about these images are:
237
238	`#^' (time) is an image of letter `T', while `#@' (zone) is an image
239	of letter `Z'. These are used in timers in accordance with ISO 8601.
240
241	`#-' (dash) and `#<' (minus) may be the same image or they may be
242	different. They, too, are used in accordance with ISO 8601.
243
244There are several ways to use image directives. The first way, which is valid
245for all 23 image directives, follows the directive by a path (in double quotes),
246followed by `gif', `gd', or `xbm' (no quotes).
247
248For example:
249
250	#/ "/usr/local/share/gracula/pix/odometer" gd
251
252This tells gracula to look for default image files in the directory specified
253and to treat them as gd graphic files. So, if it needs to render the digit 0,
254and has no explicit information about its image, it will attempt to read it from
255the /usr/local/share/gracula/pix/odometer/0.gd file. If the file does not
256exist, gracula will use the built-in image for digit 0, if one exists. If
257even that fails, gracula will simply not render the image.
258
259The image for digit 0 from the above example could also be listed explicitly:
260
261	#0 "/usr/local/share/gracula/pix/odometer/0.gd" gd
262
263The second way is to define the location of the image in the image array.
264
265Fo example:
266
267	#0 [0, 0, 10, 16]
268
269This tells gracula that the image for digit 0 starts at coordinates (0, 0) of
270the array (upper left corner), and is 10 pixels wide and 16 pixels high.
271
272It is not necessary to define an image if you do not want to use it. For
273example, a date may be rendered without dashes. Simply do not define any image
274for a dash, right? Right, as long as you do not have a built-in image for a
275dash... In that case, you can instruct gracula not to use it:
276
277	#- nodefault
278
279You may also tell it explicitly that no image is defined and to use default if
280one exists:
281
282	#- default
283
284What if you use the same directive several times? Gracula will use the last one.
285Same holds true about all other directives and keywords. That way you can modify
286an active counter without editing it in a text editor. An active counter is one
287that is being used on a web site. You never want to edit it directly because
288you would lose count on anyone who was counted on the web while you were editing
289the file. Instead, you can append the changes using the double `>>' symbol.
290
291For example, suppose you want to stop using a dash in the script `counter.gcl'.
292Just enter the following from the Unix command line:
293
294	% echo "#- default" >> counter.gcl
295
296Make sure not to use the single `>' or you will overwrite the file instead of
297appending to it. Also, the `%' denotes your command line prompt, not something
298you should type. Your prompt may be different.
299
300* The `utc' and `stz' directives
301  ------------------------------
302
303The web is international. Displaying date and time is meaningful only in
304relation to a time zone.
305
306The `utc' directive tells gracula to use Universal Time Coordinated (previously
307known as GMT), while the `stz' directive tells it to use "Server Time Zone,"
308i.e., the time zone your web server considers its own.
309
310Optionally, these two directives may be followed by a `+' or a `-' and the
311time difference from utc or stz in SECONDS.
312
313For example, www.whizkidtech.net is hosted by pair Networks in Pittsburgh.
314Its stz is Eastern Zone, whether standard or daylight-saving, depending on the
315time of the year. But I want the timers to be shown using the Central Zone,
316because I live in that zone. So, I use the following directive:
317
318	stz - 3600
319
320That tells gracula to display time and date as it is one hour (3600 seconds)
321West of stz.
322
323If my web site was hosted by a California host, I would use:
324
325	stz + 7200
326
327because I am 2 hours East of California. Note that this is an arithmetic
328expression, hence the plus sign is not optional.
329
330* The `count' variable
331  --------------------
332
333This is where gracula keeps track of the count. Unless inhibited, gracula
334increases this value by 1 each time it runs the script. It can come in these
335forms:
336
337	count = 1234
338
339This will set count to 1234
340
341	count = ${COUNT}
342
343This will set count to the value specified in environment variable COUNT. If
344the variable starts with digits 1 - 9, gracula treats it as a decimal number;
345if with 0x, as a hexadecimal number, or if with 0, as an octal number. This is
346the same convention as used by the C programming language. If the environment
347variable does not start with a number, or if it does not exist, count will be
348set to 0.
349
350Note that this will only work with the INITIAL value. Next time around, the
351count will be increased by 1 again.
352
353	count = `someprogram -options`
354
355This works similar, except it will read the stdout output of the program
356specified and set the count to its value. Again, it works only the first time.
357But, if you want it to work every time, use the `-n' command line option which
358prevents gracula from compiling a new version of the script. That way, every
359time is the first time, in a manner of speaking.
360
361Better yet, use the `nocompile' directive (new to version 2.30). Unlike the `-n'
362command line option it cannot be overridden from the command line. So even if
363some malicious cracker runs your script using the `-N' option, gracula will not
364compile the script. You can always change it later by appending `nocompile none'
365or `nocompile default' to your script.
366
367By the way, you can use a script to do nothing but produce the count, then
368use different scripts to display the count using different images.
369
370For example, create a simple counter, simple.gcl:
371
372	#!/usr/local/bin/gracula
373	count = 1
374
375This counter will output its count as text to stdout without inserting any
376commas, then increase the value of count.
377
378Then you can create several scripts which look something like this:
379
380	#!/usr/local/bin/gracula
381	#/ "/usr/local/share/gracula/pix/dir" gd
382	nocompile
383	count = `/usr/local/bin/simple.gcl -lot -1`
384
385Each time you run one of these scripts, they will get their count from
386simple.gcl, and display it using whatever images are defined in the script.
387(The `-l' (local) option tells it not to output the HTTP header information,
388the`-o' option to omit commas from the output, and the `-t' option to output
389text rather than a gif image. The `-1' option makes sure simple.gcl does not
390print extra leading zeros in its output. They would make your script interpret
391the number as being octal rather than decimal.)
392
393Now, let's try something more advanced. Suppose you want to show a random count
394each time you run your script, but you want to keep track of how many times
395it was run. You produce a simple program that prints a random number to stdout.
396Let's assume you call it `random'. But how do you use it?
397
398If you do something like:
399
400	nocompile
401	count = `/usr/local/bin/random`
402
403it will show the random counter every time, but it will not keep track of how
404many times the script was run because of the nocompile direction. But if you
405remove the nocompile direction, it will show a random number the first time,
406and then just increase it by one the next time.
407
408The solution becomes simple if you recall that you can use any keyword and
409directive repeatedly, and gracula will use the last occurence:
410
411	#!/usr/local/bin/gracula
412	#/ "/usr/local/share/gracula/pix/dir" gd
413	nocompile
414	count = `/usr/local/bin/simple.gcl -c`
415	count = `/usr/local/bin/random`
416
417In this script, you run simple.gcl with the `-c' option (compile only). It will
418produce no output, just recompile the script, thus increasing its count. The
419value of count will be 0 (because of no output). Then you run `random' and
420assign its output to count, and display it.
421
422Note that you can use an environment variable or a program anywhere in your
423script where an integer is expected.
424
425You can do the same whenever a string is expected. For example:
426
427	#/ ${PICDIR} gd
428
429In some cases, GCL allows you to use either a string or an integer... In that
430case, the environment variable or program output is interpreted as a text
431string unless it is followed by an exclamation point, in which case it is
432treated an an integer. However, you can only use the exclamation point whenever
433such an ambiguity would exist. Otherwise you cannot use it.
434
435Just remember, if you want it to happen every time, use the `nocompile'
436directive. If you want it to happen only the first time, do not use the
437`nocompile' directive.
438
439Here is another example of advanced GCL use. In this case, you write a program
440that returns the name of the directory containing your images, depending on the
441season. This will allow you to automatically adjust the imagery depending on
442the time of the year. Let's call that program seasgra (for seasonal graphics).
443
444Here is the magic script:
445
446	#!/usr/local/bin/gracula
447	nocompile
448	#/ `/usr/localbin/seasgra` gd
449	count = `/usr/local/bin/simple.gcl -lot -1`
450
451A four-line script that displays a counter of a different design depending on
452the season. How is that for power and flexibility? Heck, you can probably come
453up with ideas of your own! If you do, please share them with everyone on the
454gracula mailing list.
455
456Anyway, back to the count variable and its options.
457
458	count++
459
460This will increase current value of count by 1.
461
462	count--
463
464This will decrease current value of count by 1. You can also use it to test
465what the biggest possible count is.Just do the following:
466
467	count = 0
468	count--
469
470This will assign 0 to the count, then decrease it by 1. But because count is
471an unsigned integer, it will have the same effect as assigning the highest
472possible value to it (if you do not know how binary numbers are represented
473insode computers, just take my word for it please).
474
475Then run it with the -lt switch. For example, if your script is named
476script.gcl, type:
477
478	% gracula script.gcl -lt
479
480It will print the highest possible value of the counter. This depends on your
481system and on the compile-time options you used. (See below about the advanced
482use of count.)
483
484	count += 1000
485	count += ${OFFSET}
486	count += `program -options`
487
488This will increase the count by 1000 (or by the value of the environment
489variable OFFSET, or the output of program).
490
491	count -= 1000
492	count -= ${OFFSET}
493	count -= `program -options`
494
495This will decrease the count by the value specified.
496
497Remember, if you want to change the count of an active counter, append the
498appropriate command from the Unix command line, do not edit the file:
499
500	% echo "count += 10000" >> counter.gcl
501
502Incidentally, you can use $(OFFSET) instead of ${OFFSET}. And as long as
503the name of the environment variable consists of characters only, you can
504skip the brackets altogether (i.e., you can use just $OFFSET).
505
506* Advanced use of count
507  ---------------------
508
509Starting with version 2.40, count is treated as a true variable. That means
510you can use it wherever an integer value is expected. You can even assign it
511to itself:
512
513	count = count
514
515I am not sure why you would want to do that, but it is legal GCL.
516
517You can also assign a negative value to it, e.g.:
518
519	count = -1
520
521You could do it indirectly before anyway (count = 0 count -= 1), so why not
522allow it.
523
524Further, you can use the new `signed' keyword to tell gracula you want to
525display the count as a signed value. And you can use the `unsigned' keyword
526to tell it to treat everything as unsigned values (that is the default).
527
528More on that when we talk about registers.
529
530* The `print' keyword
531  -------------------
532
533Used instead of the count keyword, it allows you to display an arbitrary value.
534It accepts a string as its parameter. The string should contain digits 0 - 9,
535and any of the GCL characters for dash (-), comma (,), space (~), dot (;),
536colon (%), minus (<), plus (>), time (^), and zone (@).
537
538Additionally, it will accept their "real-life" counterparts (:+TZ .) and convert
539them internally to its own representation. It will ignore anything else.
540
541And, of course, it will accept an environment variable or output of a program.
542
543Examples:
544
545	nocompile
546	print "1950-04-23^00%30>01"
547
548This will display the day, time, and time zone of my birth.
549
550Note that it will not group digits nor separate groups by commas. However,
551if you follow the string by an exclamation point, it will assume the string
552contains a textual representation of an integer (decimal, octal, or hexadecimal)
553and then it will use commas for separation.
554
555Example:
556
557	nocompile
558	print `/usr/local/bin/sec2000` !
559
560This will behave exactly like the example in the COUNTDOWN TO 2000 section.
561However, it cannot be followed by something like count -= 3600. This is because
562the `print' and the `count' keywords cancel each other out! The `print' keyword
563does not set the value of `count', it defines a string to be printed.
564
565The `print' keyword first appeared in v2.30 of GCL/gracula.
566
567* Text strings
568  ------------
569
570A text string is enclosed in double quotes ("). Any character may be escaped
571by a backslash - this allows you to have a double quote inside the string.
572Only the double quote and backslash itself need to be escaped. There are no
573special escaped characters. So "\n" is the same as "n" - it does not denote
574a newline (as it does in C).
575
576The string must end on the same line it was started on. However, if your editor
577does not allow you to do that, you can use a backslash as the last character
578on the line, then continue on a different line. For example, these two strings
579are identical:
580
581"/usr/local/share/gracula/pix/dir"
582
583"/us\
584r/lo\
585
586cal/\
587
588sha\
589re\
590
591/\
592
593gracula/\
594pi\
595
596x/dir"
597
598Same rules apply to shell calls enclosed in backticks, e.g.
599
600`/u\
601
602sr/local\
603
604/\
605\
606
607bin/\
608
609sec\
610
6112000\
612
613`
614
615is the same as `/usr/local/bin/sec2000`.
616
617It is NOT true of GCL keywords, integers, and directives! However, operators
618may be split (without a backslash), e.g.
619
620	count
621	 -
622	 =
623	1000
624
625is the same as count -= 1000, or, for that matter, count-=1000. Similarly,
626
627	count
628	-
629	-
630
631is the same as count-- or count --.
632
633This is not to suggest you should code like that! It is simply to inform you
634how GCL and gracula process text strings.
635
636* The `now' function
637  ------------------
638
639This function returns the number of seconds since the epoch. It is the same
640as the `time()' function of C.
641
642* The registers
643  -------------
644
645Starting with version 2.40, GCL contains four registers named a, b, c, and d.
646Unlike everything else in GCL, the register names are NOT case sensitive, so
647you can also refer to them as A, B, C, and D. Indeed, as of version 3.0, GCL is
648no longer case sensitive, so you can freely mix upper and lower case.
649
650Registers can be assigned values (their starting value is 0). They can be
651used anywhere an integer is expected. And they can perform the four arithmetic
652operations of addition, subtraction, multiplication, and division.
653
654Suppose you want to display a random count using random colors. You need to
655use an array image with black digits, so you can use the `colorize' keyword.
656
657Define environment variables RNDMUL and RNDADD to produce random numbers (of
658course, you can just hardcode their values in the script). Then do something
659like this:
660
66101:	unsigned
66202:	nocompile
66303:	a  = now
66404:	a *= ${RNDMUL}
66505:	a += ${RNDADD}
66606:	b  = a
66707:	b *= ${RNDMUL}
66808:	b += ${RNDADD}
66909:	c  = b
67010:	c *= ${RNDMUL}
67111:	c += ${RNDADD}
67212:	d  = c
67313:	d *= ${RNDMUL}
67414:	d += ${RNDADD}
67515:
67616:	colorize a b c
67717:	count = d
678
679Do not use the line numbers, of course. They are here only so I can analyze
680the code for you. Nor are the real line numbers, since you will want to
681define your images first (or last).
682
683So, what does it do? Line 01 tells gracula to treat everything as unsigned
684values. This is the default, but you could have used `signed' somewhere
685else in the code.
686
687Line 02 prevents gracula from compiling your code, as that would remove it
688all and only keep the final values. The result would no longer be random.
689
690Line 03 uses the `now' function as the seed for the random number generator.
691Lines 04 and 05 turn the seed into a random number. Lines 06, 09, and 12, seed
692the rest of the registers. The rest of the lines, up to 14 calculate additional
693random numbers and store them in the registers.
694
695Line 15 is there for increased readability. Line 16 changes black pixels in
696the array image to some random color. Line 17 sets the count to yet another
697random value.
698
699Go ahead, play with it. Just don't forget to set the environment variables.
700
701Note that you can use the `signed' and `unsigned' keywords repeatedly to
702influence your arithmetics. Example:
703
704	a = -15
705	b = -2
706	c = a
707	signed
708	c /= b
709	unsigned
710	a /= b
711
712Can you figure out the final values of A and C?
713
714Because the c /= b statement divides two signed integers, C will be 7. But
715because the integers are treated as unsigned in the final division, A = 0.
716That is because -2 is represented by a larger unsigned binary number than
717-15...
718
719What if you divide by 0? GCL will simply ignore it. So, the result would be
720the same as if you divided by 1 (not because that is mathematically correct
721but because no division actually takes place).
722
723* Assignment operators
724  ------------------
725
726The following operators are available to assign values to registers and the
727count variables:
728
729	=    assignment. E.g. A = count will assign the value of `count'
730	     to register A.
731
732	+=   addition. A += B will add the value of register B to register A.
733
734	-=   subtraction. A -= 2 will subtract 2 from register A.
735
736	&=   binary AND. A &= B will assign the result of binary AND operation
737	     of the values of registers A and B.
738
739	|=   binary OR. A |= pop will pop off a value from the stack and store
740	     the result of the binary OR of the value of register A and the
741	     popped value in A.
742
743	^=   binary XOR. A ^= C will store the result of the binary XOR
744	     operation of the bits of A and C in A.
745
746	++   increment. A++ will increase the value of A by 1.
747
748	--   decrement. A-- will decrease the value of A by 1.
749
750Except for `++' and `--' all assignement operators have a left hand side (LHS)
751and right hand side (RHS). The `++' and `--' assignment operators have only
752LHS.
753
754A register or a variable are the only acceptable LHS. Any numeric expression
755may go on the RHS. For example:
756
757	count += a * 3 + random % c + b == d ^^ pop - now
758
759Here `count' is LHS, `+=' is an assignment operator. The rest of the assignment
760is is the RHS.
761
762As with all GCL operators, white space is ignored, so you can write:
763
764	count
765	+
766	+
767
768Or, you can write the above example as:
769
770	count+=a*3+random%c+b==d^^pop-now
771
772Note that the increment and decrement operations are true assignments in GCL.
773Therefore, they must FOLLOW the register or variable they modify. In other
774words, a-- is an assignment (i.e., it is functional equivalent of a = a - 1),
775while --a is a numeric expression. That is, b = --a is the same as b = a. You
776can think of it as b = - (-a) to see why.
777
778* More on `signed'
779  ----------------
780
781Note that addition, subtraction, and multiplication, result in the same
782value whether it is signed or unsigned. But division does not. That has
783nothing to do with GCL, by the way: That is the way most computers work.
784
785Whether the result displayed by gracula is signed or unsigned depends on the
786FINAL `signed' or `unsigned' keyword used in your script. It does not matter
787whether it appears before or after you assign the final value to `count'.
788
789However, when assigning a value from registers, environment, program ouputs,
790or the `count' variable to anything that expects an unsigned value (such
791as `colorize'), the curent state of `signed' or `unsigned' is considered
792at the time of assignment. If the current state is `signed' and the value
793represents a negative value, its absolute value is assigned. If the current
794state is `unsigned', the value is assigned as is.
795
796That means that our random example would yield different color if line 01
797said `signed'. They would still be equally random, though.
798
799COUNTDOWN TO 2000
800=================
801
802The enclosed program sec2000 does nothing but print the number of seconds,
803minutes, hours, or days till the year 2000. You can use it within a GCL
804script like this:
805
806	nocompile
807	count = `/usr/local/bin/sec2000`
808	signed
809
810You can then adjust it from UTC to your time zone by adding something like
811
812	count -= 3600
813
814For more options, please read the file sec2000.c.
815
816* The GCL version
817  ---------------
818
819In version 2.40, you no longer need an external program for the countdown to
820the Year 2000. You can write it in plain GCL, just like this:
821
822	count  = 946684800
823	count -= now
824	signed
825	nocompile
826
827As simple as that! And if you want to adjust it to some other time zone, you
828can still use count -= 3600 (or whatever value), or you can simply adjust
829the 946684800 as necessary. That number, by the way, is what the value of
830`now' will be on January 1, 2000, at 00:00 UTC. At least on my Unix system.
831
832In version 3.0, you can further simplify it by using numeric expressions:
833
834	count = 946684800 - now
835	signed
836	nocompile
837
838INCLUDING FILES
839===============
840
841As of version 2.40, you can include other files in your script. Use the `#?'
842directive.
843
844Suppose you want to use Dominique Voillemot's clock.gcl to display the countdown
845to the Year 2000, you can do:
846
847	#? "/usr/local/bin/clock.gcl"
848	nocompile
849	signed
850	count  = 946684800
851	count -= now
852
853This is also useful when you want to use the same design in several counters:
854
855	#!/usr/local/bin/gracula
856	#? "/usr/local/bin/clock.gcl"
857	nocompile none	## i.e., compile
858	count = 1	## or whatever starting value you want
859
860This will compile everything, including the contents of clock.gcl into your
861script. Once it is compiled, the `#?' directive will have disappeared, so
862there is no performance hit on your counter.
863
864CONTROLLING INCREMENTS
865======================
866
867Unless inhibited by the `-i' command line switch or by the use of inhibitors,
868whenever a GCL file is compiled, the value of `count' is incremented by 1.
869This is the default behavior, but can be changed by several methods.
870
871* The `increment' keyword
872  -----------------------
873
874This keyword controls the value by which `count' is incremented. In its simplest
875form, the keyword is simply followed by an integer:
876
877	increment -1
878
879This will "increment" the count by -1, i.e., it will actually decrement it by 1.
880
881You can also define a range of incrementation:
882
883	increment [5, 11]
884
885In this case, the count will be incremented by a random number between 5 and 11.
886
887	increment [-10, 10]
888
889This will create an "oscillating" counter as the count will be increased by a
890random value between -10 and 10. That means that in the long run, the count
891will oscillate around some constant value, but in the short run it will move
892up and down.
893
894* The `fudge' keyword
895  -------------------
896
897This keyword allows you to fudge the counter by some factor. For example,
898
899	fudge 5
900
901will create the fudge factor of 5. The count will be increased by a random
902value between 1 and fudge factor * 2 - 1. So, in the case listed above, it
903will be increased by a random value between 1 and 9. That gives you an AVERAGE
904increase of 5. You will know, over the long run, that the actual number of hits
905was 5 times less than shown. This will allow you to fudge the visible count
906without it being obvious.
907
908The maximum fudge factor is 1023. If you use a higher number, GCL will truncate
909it by masking out the extra bits.
910
911If you really need a higher fudge factor, use:
912
913	increment [1, nnnn]
914
915where nnnn is your fudge factor * 2 - 1. The fudge keyword is just a shortcut
916for that notation anyway.
917
918* The `sigma' keyword
919  -------------------
920
921This keyword allows you to SIMULATE real life statistics. Statistical analysis
922often comes up with a mean and a sigma. For example, statistical analysis of
923people killed by drunk drivers in an average minute could come up with the
924mean of 1000 and a sigma of 17 (these are not actual number from those
925statistics, just a made-up example). To put it simply (and to simplify the
926science of statistics), in any given minute the number of people killed by
927drunk drivers would be 1000 +/- 17, or anywhere between 983 and 1017. As I
928said, this is a simplification. In reality, in any given minute the actual
929number can be outside of that range, but in most minutes it will be somewhere
930within that range.
931
932Now, you could create a web site against drunk driving in which you would
933create a simulation of how many people were killed in the last minute. You
934would use the sigma keyword, like this:
935
936	sigma 17 1000
937
938In other words, the `sigma' keyword is followed first by the sigma, then by
939the mean.
940
941If you use the `sigma' keyword, the `count' variable will be ignored (indeed,
942the GCL compiler will set it to mean).
943
944The three keywords described in this section are mutually exclusive. That is,
945if you follow a `sigma' by a `fudge', `sigma' will be discarded, and `fudge'
946will be used. Or, if you follow `increment' by `sigma', `increment' will be
947discarded, and `sigma' will be used.
948
949RANDOM NUMBERS
950==============
951
952The `random' function of GCL can be used anywhere an integer is expected.
953So, you can rewrite the script for the display of a random number in
954random colors shown above like this:
955
956	#!/usr/local/bin/gracula
957	#? "/usr/local/bin/black.gcl"
958	colorize random random random
959	count = random
960	nocompile
961
962Not only is this simpler, but the random number generator used by gracula is
963better than the one in the example script. Or so I think. :-)
964
965Note that `random' will always produce a positive random number. So, if you
966compiled gracula to use 64 bits, the random number will have 63 significant
967bits.
968
969However, there also is the `srandom' function which will produce a random number
970that may be positive or negative. Again, if you compiled gracula to use 64 bits,
971the srandom function will return a 64-bit random number.
972
973GROUPING DIGITS
974===============
975
976By default, the GCL interpreter separates digits into groups of three and
977displays a comma between them.
978
979This behavior can be modified with the `group' keyword:
980
981	group 4
982
983This tells the interpreter to use groups of 4 rather than 3.
984
985	group dots
986
987This tells it to use dots instead of commas.
988
989	group spaces
990
991Here, GCL will uses spaces as a separator instead of commas.
992
993	group 3 commas
994
995This is the default behavior. Note that the `-o' command line switch tells
996gracula to omit grouping altogether. You can also effectively turn off grouping
997by using a large value with the `group' keyword:
998
999	group 1000
1000
1001This effectively turns off grouping since the maximum number of digits gracula
1002will display is 127. However, the `-o' switch is more effective and flexible.
1003
1004Note that in the future the default behavior will probably change to the use
1005of spaces as the default separator to conform with international standards.
1006To make the transition painless, the compiler of the version 2.40 will write
1007`group commas' to the compiled GCL scripts even if it is the default.
1008
1009THE GCL STACK
1010=============
1011
1012In some cases four registers may not be enough. GCL also contains a stack
1013which is 16 levels deep. You can push values on it, pop them, and you can
1014read the current value on the top of the stack without popping it.
1015
1016Note that the contents of the stack are undefined until you push something
1017on them. They are also undefined after you pop everything you pushed.
1018
1019If you push more than 16 values on the stack without popping them, the values
1020on the bottom of the stack will be lost.
1021
1022* The `push' keyword
1023  ------------------
1024
1025You can push a value on the stack by using the `push' keyword followed by
1026the value.
1027
1028Examples:
1029
1030	push -5		- this pushes -5 on the top of the stack
1031	push !8		- this pushes 0 (logical not 8) on the tos
1032	push ~count	- pushes count with its bits reversed on tos
1033	push ${VALUE}	- pushes the integer value in the environment
1034			  variable VALUE on the top of the stack
1035	push tos	- pushes the value of the top of the stack on
1036			  the top of the stack
1037	push pop	- pops the top of the stack and pushes it right
1038			  back. Quite useless, but possible
1039
1040* The `pop' function
1041  ------------------
1042
1043This function removes the value from the top of the stack and returns its
1044value.
1045
1046Example:
1047
1048	push 1
1049	push 2
1050	push 3
1051	colorize pop pop pop
1052
1053This is the same as `colorize 3 2 1' (remember, the values are popped in the
1054opposite order as they are pushed).
1055
1056* The `tos' function
1057  ------------------
1058
1059This function returns the value of the top of the stack without popping it.
1060
1061Example:
1062
1063	push random
1064	colorize tos tos pop
1065
1066This will change the black pixels in the array image to a random shade of gray.
1067But can you see something wrong with it? While it is valid GCL, it may produce
1068a color identical to the background.
1069
1070That is easily fixed. Suppose you show this counter on a white background. You
1071may limit the range of available shades of gray:
1072
1073	push random & 127
1074	colorize tos tos pop
1075
1076Or:
1077
1078	push random % 128
1079	colorize tos tos pop
1080
1081NUMERIC EXPRESSIONS
1082===================
1083
1084The addition of numeric expressions was one of the two reasons to bump up the
1085major version from 2 to 3 (control statements was the other).
1086
1087A numeric expression can be a variable (count), a function (tos, pop, now,
1088random, srandom, signed, unsigned), a register (A - D), a constant, or a value
1089read from an environment variable or the output of a program.
1090
1091Note about `signed' and `unsigned': You have already learned about these
1092keywords as directives to tell the GCL interpreter whether to treat numbers
1093as signed or unsigned. In numeric expressions, however, they are used as
1094functions which return 0 or 1 depending on the current state defined by the
1095signed and unsigned directives.
1096
1097Additionally, a numeric expression can be a numeric expression followed by
1098an arithmetic or logical operator followed by a numeric expression.
1099
1100Also, a numeric expression can be a numeric expression followed by the `?'
1101operator, followed by a numeric expression, optionally followed by ':' and
1102another numeric expression.
1103
1104Finally, a numeric expression can be a unary operator followed by a numeric
1105expression.
1106
1107The last three paragraphs should be read recursively (e.g. -+-+a is the unary
1108operator `-' followed by the unary operator `+' followed by the unary
1109operator `-' followed by the unary operator `+' followed by the register A).
1110
1111Any numeric expression may be surrounded by parentheses. These are used to
1112modify the operator precedence. A numeric expression surrounded by parentheses
1113is evaluated before any operator outside the parentheses is applied. E.g.,
11145 - 7 + 2 yields 0, while 5 - (7 + 2) yields -4.
1115
1116Examples of numeric expressions are:
1117
1118	random
1119	tos * a
1120	`sec2000` / (60 * 60 * 24)
1121	a ^^ b || !c ? now : 0
1122	(a ^^ b || !c) * now
1123
1124Note that the last two examples yield the same result.
1125
1126* Operators
1127  ---------
1128
1129The following operators exist in GCL, in increasing order of precedence:
1130
1131	? ?:
1132	||
1133	^^
1134	&&
1135	|
1136	^
1137	&
1138	== !=
1139	< <= > >= <>
1140	<< >>
1141	+ -
1142	* / %
1143	! ~ + - <> \ (unary)
1144
1145C programmers will recognize most of GCL operators. The rest of them I had to
1146make up.
1147
1148The very first one, `?', is a result of GCL philosophy of graceful recovery.
1149Because GCL is often used as a CGI program, it never aborts the interpretation
1150of a script. Whenever it encounters a syntax error, it tries to recover from it
1151gracefully. It does that by assuming that when it sees something that does not
1152belong there, that something is the first keyword of the next statement.
1153
1154Originally, I was adding the C ?: operator exactly as in C. For example:
1155
1156	count = a > 0 ? 1000 : 2000
1157
1158That is an equivalent of:
1159
1160	if a > 0 count = 1000 else count = 2000
1161
1162I had to decide how to recover from a syntax error in which you forget to type
1163the `: 2000' part of it. Once I came to a decision, it made sense not to
1164consider this construct a syntax error at all, but valid GCL. After all, if GCL
1165accepts it in a predefined way, it is not an error, it is part of the language.
1166
1167As a result the `?' operator was born. It returns the expression on the left of
1168it if that expression is not 0, otherwise the expression on the right.
1169
1170For example:
1171
1172	a = b ? c
1173
1174is the equivalent of:
1175
1176	if b a = b else a = c
1177
1178Another operator not found in C is `^^'. This is the logical XOR operator:
1179
1180	a ^^ b
1181
1182This returns 1 if either a or b is 0 and the other in not zero. If they are both
11830 or neither is 0, it returns 0. For all practical purposes it is the shortcut
1184version of:
1185
1186	a && !b || !a && b
1187
1188The `<>' operator compares the value on its left to the value on its right, and
1189returns -1, 0, or 1 depending on the result of the comparison:
1190
1191	a <> b
1192
1193This is a shortcut way of the following:
1194
1195	a < b ? -1 : a > b ? 1 : 0
1196
1197There also is a unary operator `<>' which returns -1 if the value to its right
1198is negative, 1 if it is positive, 0 if it is 0. So what will this return:
1199
1200	<>-3
1201
1202Either 1 or -1. How so? Remember, by default all numeric values are considered
1203unsigned in GCL unless you override it with the signed statement. So, if the
1204current state is unsiged, <>-3 will return 1, otherwise it will return -1.
1205
1206The unary `\' operator returns the absolute value of the expression on its
1207right. What that means, again, depends on the signed or unsigned state. So,
1208\-3 can return -3 (which is actually a very big unsigned number) or 3.
1209
1210Please note that not all operators return a different result depending on the
1211current state of signed.
1212
1213The `>', `<', `>=', '<=', '<>', `/', `%', and `\' depend on the current state
1214of signed. The rest of them (including `-') do not.
1215
1216Incidentally, `a / 0' and `a % 0' are mathematically undefined. GCL ignores
1217them: Both operations will return `a'.
1218
1219Most operators are evaluated from left to right. `3 - 2 + 7' yields 8, not -6,
1220because it is the same as (3 - 2) + 7, not 3 - (2 + 7).
1221
1222Similarly, `6 / 3 * 4' will return 8, not 0, because it is the same as (6 / 3)
1223* 4, not 6 / (3 * 4).
1224
1225The comparison and shift operators are evaluated from right to left. Thus,
1226`1 << 1 << 2' equals 16, not 8, because it is the same as 1 << (1 << 2) ,
1227not (1 << 1) << 2.
1228
1229Note: If you want, you may use `=' for comparison (instead of '=='). You may
1230also use ':=' for assignment (e.g. count := 1000). This is to accomodate
1231Pascal programmers.
1232
1233FLOW CONTROL
1234============
1235
1236GCL is designed with maximum speed in mind. It is often used on the web to
1237display access counters. On a busy web site it has to be able to handle many
1238counter request in rapid succession.
1239
1240For that reason, GCL is designed in such a way that it can be processed in
1241one pass. That means, a GCL file is processed statement after statement, moving
1242forward, never looking back. GCL contains no loops, such as `for', `while',
1243`until', or whatever they are called in various languages.
1244
1245It does, however, contain several conditional statements that do not require
1246looking back.
1247
1248* The `if-then-else'  statement
1249  -----------------------------
1250
1251The `then' keyword is optional. Pascal programmers are used to it, C programmers
1252are not. Take your pick. The basic syntax is:
1253
1254	IF expression THEN statement ELSE statement
1255	IF expression statement ELSE statement
1256	IF expression THEN statement
1257	IF expression statement
1258
1259Expressions were explained above. If an expression unequals 0, the statement
1260is executed. Otherwise, it is not. Or, in the case of the if-else constructs,
1261if expression unequals 0, the first statement is executed, otherwise the
1262second one.
1263
1264Note that you may place a comma after the expression and after the else if you
1265feel the urge. For that matter, you can place a comma anywhere. Or a semicolon.
1266Or a period.
1267
1268Example:
1269
1270	If a = 15, then count = 30. Else, count = 55.
1271
1272This is the officially recommended style for GCL programs.
1273
1274Under GCL, everything that is not an expression is a statement. That includes
1275assignments, directives, even the #! construct which is there only for the
1276command shell. It is important to know what constitutes an individual statement.
1277For example, `signed count = pop' are TWO statements, not one. The first one
1278is `signed', the second `count = pop'. So if you write something like:
1279
1280	if a == 15 signed count = pop
1281	else unsigned count = random
1282
1283You will get a syntax error, and you will always get un unsigned random count.
1284This is what will really happen:
1285
1286	if a == 15 signed	## change state to signed if a == 15
1287	count = pop		## always happens
1288	else			## SYNTAX ERROR - reported and forgotten
1289	unsigned		## always happens
1290	count = random		## always happens
1291
1292Note that you MAY terminate any statement with a semicolon, comma, or a period.
1293You certainly do not have to, but it is the officially recommended GCL style.
1294In the above case the error would be immediately evident had you written it this
1295way:
1296
1297	If a == 15, signed, count = pop.
1298	Else, unsigned, count = random.
1299
1300Can you achieve what you really want here? Certainly. GCL allows you to use
1301compound statements. A compound statement is a series of statements surrounded
1302by squiggles. This is just like C. Or, surrounded by `begin' and `end'. This
1303is just like Pascal.
1304
1305So, our above example can be properly rewritten as:
1306
1307	if (a == 15) {
1308		signed;
1309		count = pop;
1310	}
1311	else {
1312		unsigned;
1313		count = random;
1314	}
1315
1316The parentheses around the `a == 15' expression are not required but C
1317programmers are used to them.
1318
1319Or, you could rewrite it the Pascal way:
1320
1321	IF A = 15 THEN
1322	BEGIN
1323		Signed;
1324		Count := Pop
1325	END
1326	ELSE
1327	BEGIN
1328		Unsigned;
1329		Count := Random
1330	END.
1331
1332Or in several other ways... The recommended style is:
1333
1334	If a = 15, { signed, count = pop }.
1335	Else, { unsigned, count = random }.
1336
1337Except for the squiggles, it looks almost like regular human language.
1338
1339As an exercise, can you figure out what this one does:
1340
1341	if signed unsigned else signed
1342
1343And how does it differ from:
1344
1345	signed ? unsigned : signed
1346
1347Hint: it does differ. One is a statement, the other an expression.
1348
1349* The `tri' statement
1350  -------------------
1351
1352The if-else construct only offers a choice between two options. It is often
1353necessary to choose from three options. If you check the C source code for
1354gracula, especially the macros defined in gcl.h, you will see how often that
1355is the case in this program alone.
1356
1357The `tri' statement follows this syntax:
1358
1359	tri expression
1360	statement
1361	statement
1362	statement
1363
1364This is identical to the following:
1365
1366	a = expression
1367	if a < 0 statement
1368	else if a == 0 statement
1369	else statement
1370
1371Of course, the tri statement is simpler, and does not waste a register.
1372As an example, let us assume we have three GCL scripts which use completely
1373different graphics. The scripts are called counter1.gcl, counter2.gcl, and
1374counter3.gcl. They are located in /usr/local/bin.
1375
1376Further, we have a counter we want to use to get the count from, and save
1377the next value of count in. It is called main.gcl, and resides in the same
1378directory. We would like to randomly choose one of the three scripts for the
1379graphical appearance of a counter. Here is a script to accomplish just that:
1380
1381	#!/usr/local/bin/gracula
1382	tri random % 3 - 1
1383	#? "/usr/local/bin/counter1.gcl" ;
1384	#? "/usr/local/bin/counter2.gcl" ;
1385	#? "/usr/local/bin/counter3.gcl" .
1386	nocompile
1387	count = `/usr/local/bin/main.gcl -lot -1`
1388
1389Here, `tri' is followed by the expression `random % 3 - 1'. This produces a
1390random number between -1 and 1. The fact we have not used `signed' is
1391irrelevant: The tri condition is always treated as a signed value.
1392
1393The condition is followed by three include statements. Gracula will only
1394include one of them, depending on the value of the randomly calculated
1395condition. Regardless of what any of the include files say about the
1396value of `count' (or even if they use the `print' statement), it will be
1397overriden by the value returned from main.gcl. Please note that the `-lot'
1398option is very important. The `-l' tells main.gcl not to send out the
1399http header (which would evaluate to 0). The `-o' switch tells it not to
1400insert commas (or spaces, dots...) in the result (which would make us
1401read only the value up to the first comma). The `-t' switch will force
1402it to give us text, not GIF.
1403
1404What about the `-1'? It will override any GCL command that may be telling
1405main.gcl to show at least a certain number of digits. Without it, main.gcl
1406might send us the count with some leading zeros and gracula would think it
1407was an octal number rather than decimal.
1408
1409The semicolons and the period after the statements are optional. I put them
1410there to indicate to you where each statement ends.
1411
1412How about a counter that displays positive values in blue, negative ones in
1413red, and zero in black? Create a script which uses an array image of black
1414digits, use some other script (like main.gcl above) to give you the count,
1415then end your script with:
1416
1417	tri <>count
1418	colorize 255 0 0
1419	colorize 0 0 0
1420	colorize 0 0 255
1421
1422Don't forget to use `nocompile' somewhere in the script!
1423
1424* The array statement
1425  -------------------
1426
1427Sometimes we need to make choices from any number of options. The array
1428statement gives us a condition and an array of options. C programmers will
1429immediately think of the C switch statement. It is similar but much more
1430powerful. Here is its basic syntax:
1431
1432	[ expression
1433		expression statement
1434		expression statement
1435		...
1436		expression statement
1437		default statement
1438	]
1439
1440There can be any number of `expression statement' and `default statement'
1441occurances. They are evaluated and executed, or not, in the order you list
1442them.
1443
1444The first expression is evaluated. Each of the other expressions is compared
1445to the first expression. If they are equal, the statement is executed. If not,
1446it is not executed.
1447
1448What about default? Think of it as "none of the above". If none of the
1449expressions evaluated before the default statement was equal to the first
1450expression, the default statement is executed.
1451
1452The fact that another default statement may have been executed will not stop
1453another default statement. Otherwise, it would make no sense to allow for more
1454than one default statement.
1455
1456More than one expression may equal to the first expression. All of their
1457corresponding statements will be executed.
1458
1459Any of these expressions can be constants, variables, functions, arithmetic
1460expressions, whatever... But here is just a simple example which does the same
1461as the one listed in the paragraph on the `tri' statement:
1462
1463	#!/usr/local/bin/gracula
1464	nocompile
1465	[ random % 3
1466		0 #? "/usr/local/bin/counter1.gcl"
1467		1 #? "/usr/local/bin/counter2.gcl"
1468		default #? "/usr/local/bin/counter2.gcl"
1469	]
1470	count = `/usr/local/bin/main.gcl -lot -1`
1471
1472I think this one is fairly self-explanatory.
1473
1474INHIBITORS AND RELAYS
1475=====================
1476
1477Inhibitors have been in GCL since the beginning but I do not believe I talked
1478much about them. That's actually good because I discovered a weird bug in them
1479while working on relays. Relays are new to v3.0 (although I had them in mind
1480much earlier).
1481
1482Both inhibitors and relays are conditional statements. But do not confuse them
1483with flow control we talked about before. They do not control the flow of
1484your program, but rather what your program will or will not do. Their most
1485obvious use is for web security. And yes, they really only make sense when
1486used on the web (as I discuss below, GCL has perfectly good uses off the
1487web, too).
1488
1489Because both inhibitors and relays use the same type of conditions, let me
1490talk about those first.
1491
1492* Conditions
1493  ----------
1494
1495I repeat, conditions have nothing to use with flow control (if-else, and such).
1496Flow control uses EXPRESSIONS, not conditions. You cannot use an expression for
1497a condition. Nor can you replace a condition with an expression.
1498
1499Also, expressions are used before the statement they modify. Conditions are part
1500of the statement itself. Indeed, they are always at the END of the statement.
1501
1502A condition always starts with either `when' or `unless'. This is followed by
1503one of three possibilities:
1504
1505	from string
1506	cookie string = string
1507	string = string
1508
1509By string I mean a quoted string, i.e., some text enclosed in double quotes.
1510
1511The string following `from' should be a valid email address, such as
1512"me@mydomain.com".
1513
1514The `from "me@mydomain.com"' condition is true if the caller's browser tells
1515your web server that the caller's email address is me@mydomain.com. Otherwise,
1516the condition is false. Indeed, it may be false even if that IS the caller's
1517email address, but his browser does not tell your server about it. This is
1518often the case, no thanks to spammers. So, the from condition is generally
1519unreliable.
1520
1521The `cookie' condition is useful if your web server sends http cookies to
1522users. Cookies come in the form of "a=b;c=d;e=f". In this case,
1523
1524	cookie "c" = "d"
1525
1526will make the condition true.
1527
1528	cookie "a" = "b"
1529
1530will also make the condition true.
1531
1532	cookie "b" = "a"
1533
1534will make the condition FALSE. That is because in cookies "a=b" is not the
1535same as "b=a".
1536
1537Finally, the `string = string' condition is the most generic one. The string on
1538the left is the name of an environment variable. The one on the right is its
1539value (or contents). CGI programs receive such environment variables from the
1540server, and you can test them.
1541
1542For example:
1543
1544	"HTTP_REFERER" = "http://www.mydomain.com/mypage.html"
1545
1546This condition is true if your counter is being called by mypage.html on the
1547www.mydomain.com web site. Otherwise it is false.
1548
1549Now, remember, these are not the full conditions. They are preceded by either
1550`when' or `unless'. The full condition is true if `when' is followed by
1551something true, or if `unless' is followed by something false. Otherwise,
1552the full condition is false.
1553
1554* Inhibitors
1555  ----------
1556
1557An inhibitor will either inhibit the counter or not. That depends on which
1558inhibitor you are using, and on its condition.
1559
1560When a counter is inhibited, its future value is not changed. Normally, it is
1561increased by one (unless you use one of the variety of increment keywords
1562discussed earlier). That is how the next caller gets a count one higher than
1563current caller.
1564
1565Why would you want to inhibit the counter? There are two main reasons I can
1566think of, although you may come up with others.
1567
1568The first one is that you may not want to increase the counter when YOU access
1569your web page. That way you know how many people other than you visited your
1570web site.
1571
1572The other one is to prevent theft of services, or just plain malicious
1573cracking. Suppose someone does not like you, and adds the URL of your counter
1574to a highly visited web page of his. Without the use of inhibitors, your
1575counter will increase its value every time someone visits HIS page, in
1576addition to yours. You will get the false sense of having more visitors than
1577you really do. You will be upset when you compare the reported number of hits
1578with your logs. And, gods forbid, you will think GCL is not working right!
1579
1580There are two possible inhibitors: `inhibit' and `concede'. The first one
1581will inhibit the counter, the second will turn any inhibition off. Both
1582will do that only if the condition is true.
1583
1584Here is how I inhibit my counters whenever I call my web site. Although I
1585do not use cookies with my web site, I wrote a CGI page once just to send
1586myself a cookie. For the sake of argument, let's assume the cookie is:
1587
1588	"caller=adam"
1589
1590It is actually something else, but this will do for illustration. Now, all
1591I had to do is append to all my counters the following line:
1592
1593	inhibit when cookie "caller" = "adam"
1594
1595That way, when I call my web site, my counter tells me exactly how many
1596visitors I had on each page, but it does not count me. I could have used
1597the `from' condition, but I would have had to let my browser reveal my email
1598address to every web site I call, and I do not want to do that. Again,
1599no thank you, spammers!
1600
1601And how do you prevent someone else from increasing your counter maliciously?
1602The easiest way is by the use of the HTTP_REFERER (note, just one `R' between
1603the two E's). If you are not exactly sure what its value is, use the GCL
1604feature of expanding environment variables to strings like this:
1605
1606	inhibit unless "HTTP_REFERER" = ${HTTP_REFERER}
1607
1608Then call your web page. Gracula will expand it, and write the expanded version
1609to your script when it compiles it for the first time.
1610
1611After that, take a look at your script. It will contain something like this:
1612
1613	inhibit unless "HTTP_REFERER" = "http://www.mysite.com/mypage.html"
1614
1615Or whatever is right for your system.
1616
1617You may use as many inhibitors in your counter as you want. They are evaluated
1618in the order you enter them. This is important! Make sure an inhibitor does
1619not cancel one you do not want cancelled. Suppose you do something like this:
1620
1621	inhibit unless "HTTP_REFERER" = "http://mysite.com/mypage.com"
1622	inhibit unless "HTTP_REFERER" = "http://www.mysite.com/mypage.com"
1623
1624You may want that because both address the same page. But it will not work!
1625That is because the second statement overrides the first. The proper way to do
1626it is:
1627
1628	inhibit unless "HTTP_REFERER" = "http://mysite.com/mypage.html"
1629	concede when "HTPP_REFERER" = "http://www.mysite.com/mypage.html"
1630
1631Can you see the difference? The second statement makes an exception to the
1632first one instead of overriding it.
1633
1634What if you want to change an active counter's inhibitions? Remember, you
1635can use as many inhibitors as you want, so just appending new ones will not
1636work. And as discussed elsewhere, you never want to edit an active counter
1637because you will lose count of whoever calls your web site while you are
1638editing. So to change your inhibitors to the above, first create a text file,
1639like this:
1640
1641	inhibit none ## this wipes out all existing inhibitors
1642	inhibit unless "HTTP_REFERER" = "http://mysite.com/mypage.html"
1643	concede when "HTTP_REFERER" = "http://www.mysite.com/mypage.html"
1644
1645Assuming the text file is named `changes' and your counter `mycounter.gcl',
1646just type the following your counter's directory:
1647
1648	cat changes >> mycounter.gcl
1649
1650Don't forget to use the DOUBLE `>>' or else you will overwrite the counter
1651instead of appending to it.
1652
1653And, by the way, using `concede none' would work as well.
1654
1655* Relays
1656  ------
1657
1658Relays will redirect the caller to a different URL based on the condition.
1659This will prevent someone else from displaying your counter on his web site.
1660Or, it will allow it.
1661
1662They come in two forms:
1663
1664	relay string condition
1665	serve condition
1666
1667The condition is the same as in inhibitors. The string, in this case, is the
1668URL to wherever you want to relay the caller. It can be a graphic, or another
1669counter. The graphic can say something nasty, or something polite, that's
1670your choice. No string comes after `serve' because that is telling GCL not to
1671relay the caller somewhere else.
1672
1673Example:
1674
1675	relay "http://go.hell.to/nasty.gif" unless "HTTP_REFERER" = "..."
1676	serve from "me@mydomain.com"
1677
1678The "...", of course, needs to be your web page URL. I just did not have
1679enough room on the line to spell it out (of course, it does not have to
1680all go on one line).
1681
1682This sends every one trying to access your counter from some cracker's site
1683to go.hell.to/nasty.gif. Everyone, that is, except you (assuming your
1684browser is set up to reveal your address).
1685
1686Please note that you should not relay someone to a graphic on someone else's
1687web site unless you have their permission. Otherwise, you will be doing to
1688others what you do not want others to do to you. The best thing, in my humble
1689opinion, is to send them a banner advertising your site. While callers will not
1690be able to click through to your site, of course, they will at least learn
1691about its existence. Heck, it does not have to be just a banner, it can be
1692a full-page ad. :-)
1693
1694Suppose you want to set up a mini-server for others to use counters, but
1695you want them all to access it using the same URL. You want to redirect
1696your customers to their counters, but display some graphic in any other
1697case. Remember (from the FAQ) the `redirect' keyword:
1698
1699	redirect "http://www.mydomain.com/mybanner.gif"
1700	relay "http://www.mydomain.com/counter1.gcl" when
1701		"HTTP_REFERER" = "http://www.mycustomer1.com/home.html"
1702	relay "http://www.mydomain.com/counter2.gcl" when
1703		"HTTP_REFERER" = "http://www.mycustomer2.com/home.html"
1704	[etc...]
1705
1706This is not the most efficient way of doing it. Letting the customers use
1707the URL of their counter is more efficient. But it serves as illustration.
1708
1709Similar to what we discussed in the paragraph on inhibitors, you can use
1710`relay none' (or `serve none') when you want to start from scratch.
1711
1712One final note: Relays do not inhibit the counter. If you want a counter
1713relayed and inhibited, use both relays and inhibitors in your script. That
1714may sound like extra work, but it offers you maximum flexibility.
1715
1716* The "starts with" operator
1717  --------------------------
1718
1719Sometimes you may want to inhibit (or concede, relay, serve) an entire domain.
1720Simply replace the `=' with `:='. This is the "starts with" operator.
1721
1722Example:
1723
1724	inhibit unless "HTTP_REFERER" := "http://www.mydomain.com/"
1725
1726This will inhibit the counter unless the value of the environment variable
1727HTTP_REFERER starts with "http://www.mydomain.com/".
1728
1729Hint:
1730
1731Use the trailing slash. If you only used "http://www.mydomain.com", without
1732the slash, a malicious cracker could duplicate it. If his domain is cracker.com,
1733he can easily set up an "http://www.mydomain.com.cracker.com" and that will
1734match the requirement of the string starting with "http://www.mydomain.com".
1735But it will NOT match "http://www.mydomain.com/".
1736
1737There is no "ends with" operator because that would be completely unsafe.
1738
1739As usual, if you want allow the increase of the counter with or without
1740the "www" in your domain, use two statements:
1741
1742	inhibit unless "HTTP_REFERER" := "http://www.mydomain.com/"
1743	concede when "HTTP_REFERER" := "http://mydomain.com/"
1744
1745And so on for any other domains. Of course, you do not need to stop with
1746domains:
1747
1748	inhibit unless "HTTP_REFERER" := "http://www.mydomain.com/mydirectory/"
1749	inhibit unless "HTTP_REFERER" := "http://www.myisp.com/~myaccount/"
1750
1751All of these are perfectly valid GCL.
1752
1753THE PERSIAN FLAW
1754================
1755
1756Do you know what Persian flaw is? Perhaps everyone knows that Persians have made
1757the most beautiful carpets ever produced on this planet. Yet, every single one
1758of them has some small flaw in it.
1759
1760Is it because Persian carpet makers could not get it quite right? No! They put
1761a flaw in every carpet they made on purpose. Their reason was that only God
1762could create something perfect. So if they made a perfect carpet, they would be
1763defying God, in a way.
1764
1765I have been told repeatedly, several versions back, that GCL had achieved
1766everything a graphic counter language could. I knew that was not the case,
1767because I knew from day one all the things I wanted in it. Version 3.0 has
1768everything in that I originally planned. That is not to say I cannot come up
1769with further ideas, but they probably will be on a smaller scale.
1770
1771But I assure you that GCL is not flawless. Indeed, it contains a Persian flaw.
1772A flaw that is there by my choice. It is very subtle. Some of you, having read
1773the Introductory Tutorial, the FAQ, and this README file may have discovered it.
1774But I bet most of you did not. :-) If you feel like it, stop reading and try to
1775figure it out. You can always come back (of course, it can hit you in the mean
1776time, so you'll be probably better off reading on).
1777
1778Just to set the record straight, my motivation is completely different from the
1779Persians. As far as I am concerned, whoever or whatever designed the world we
1780live in also placed flaws into it on purpose. Not because he, she, they, or it,
1781could not make a perfect world but because it knew that a perfect world would be
1782perfectly boring. I have always held on to the belief that perfection is for
1783neurotics.
1784
1785OK, now what the heck is that flaw? Consider a section of an actual script:
1786
1787	# ... declare some images above
1788	invis 255 255 255
1789	trans
1790	align commas bottom
1791	count = 946684800
1792	count -= now
1793	signed
1794	nocompile
1795
1796You will recognize it as the script for a countdown to the Year 2000. But it
1797does not work. It always displays a negative number. Even in 1999. Obviously,
1798is should show a negative number in 2000 and later, but not in 1999. Can you
1799figure out what is wrong with it? It is the victim of the Persian flaw in GCL
1800design.
1801
1802If you still cannot see it, let's try rewriting it:
1803
1804	# ... declare some images above
1805	invis 255 255 255
1806	trans
1807	align commas bottom
1808	count = 946684800 - now
1809	signed
1810	nocompile
1811
1812But, oops, this script always shows the count of 0. Before or after the Year
18132000. Except it shows 1 during the first second of the Year 2000. Can you see
1814it yet? If not, let's rewrite it again:
1815
1816	# ... declare some images above
1817	invis 255 255 255
1818	trans
1819	align commas bottom count = 946684800 - now
1820	signed
1821	nocompile
1822
1823Remember, `align commas bottom' is either followed by an expression, or it
1824just implies a 0. And it does not matter whether the expression is on the
1825same line or another. In this case, the programmer's intent was to assign
1826a value to the `count' variable. `count = 9446684800 - now' is a valid GCL
1827assignment. But it is also a valid expression! Consider this:
1828
1829	if (count = 946684800 - now) then ...
1830
1831Aha! Because count equals 0, it evaluates to 0 any time except the first
1832second of the Year 2000 when it evaluates to 1 because at that second now
1833is equal to 946684800.
1834
1835It is quite easy to fix, by the way. Here are several solutions:
1836
1837	# ... declare some images above
1838	invis 255 255 255
1839	trans
1840	{ align commas bottom }
1841	count = 946684800 - now
1842	signed
1843	nocompile
1844
1845
1846	# ... declare some images above
1847	invis 255 255 255
1848	trans
1849	align commas bottom
1850	{ count = 946684800 - now }
1851	signed
1852	nocompile
1853
1854
1855	# ... declare some images above
1856	invis 255 255 255
1857	trans
1858	align commas bottom
1859	{}
1860	count = 946684800 - now
1861	signed
1862	nocompile
1863
1864How about this?
1865
1866	# ... declare some images above
1867	invis 255 255 255
1868	trans
1869	align commas bottom
1870	signed
1871	count = 946684800 - now
1872	nocompile
1873
1874Nope! `Signed', too can be both a statement and an expression! This will
1875work in 1999 and surprise you in 2000 by showing a very big positive number.
1876
1877But, yes, changing the order of statements to make them unambiguous is one
1878of possible solutions. Like this, for example:
1879
1880	# ... declare some images above
1881	invis 255 255 255
1882	trans
1883	align commas bottom
1884	nocompile
1885	count = 946684800 - now
1886	signed
1887
1888However, the best solution is to use the recommended coding style which
1889separates all numeric expressions by a comma, and ends each statement
1890with a period. It also starts each comment with two octothorps:
1891
1892	## ... declare some images above
1893	Invis 255, 255, 255.
1894	Trans.
1895	Align commas bottom.
1896	Nocompile.
1897	Count = 946684800 - now.
1898	Signed.
1899
1900So, by now it should be clear what the Persian flaw of GCL is: It can be
1901ambiguous on occasion. Just like real human languages are.
1902
1903NATURAL LANGUAGE PROCESSING
1904===========================
1905
1906Talking of real human languages...
1907
1908Some of the operators we have studied so far can also be replaced by keywords.
1909Instead of `&&' you can write `and'. Instead of `||' you can write `or'. Instead
1910of '=' you can write `equal' or `equals'. Instead of '>' you can write `greater'
1911or `larger'. Instead of `<' you can write `lesser' or `smaller'. Instead of `^^'
1912just use `xor'. Instead of '+' you can get away with `plus' or `positive'. And,
1913of course, instead of `-' you may use `minus' or `negative'. You can replace `%'
1914with `modulo' or `modulus'. Or `<>' with `sign'.
1915
1916Oh, and, by the way, you can use `include' for `#?' if you want. And you may use
1917`otherwise' instead of `else'.
1918
1919Big deal, you may be yawning. All right, here's something else: You can use ANY
1920word in any language anywhere in your script as long as it is not a GCL keyword.
1921And you can use commas, semicolons, periods, and apostrophes, anywhere you want,
1922except inside a numeric expression.
1923
1924All right, let me give you an example:
1925
1926	Computer,
1927
1928	This is the Captain...
1929
1930	Let's use signed numbers for this calculation.
1931
1932	If some random number is greater than another random number...
1933	Oh, let's begin by setting the value of count equal to positive 17.
1934	Also, let's colorize this somewhat. Set the red factor to 255;
1935	the green one to 0. Also, leave the blue factor at 0. That should
1936	end the result of this condition.
1937
1938	Otherwise, just make count equal negative 17.
1939
1940
1941What will GCL see here? This:
1942
1943	signed
1944	if random > random {
1945		count = +17
1946		colorize 255 0 0
1947	}
1948	else
1949		count = -17
1950
1951To make that clear, let me repeat it here with GCL keywords in capital letters:
1952
1953	computer,
1954
1955	this is the captain...
1956
1957	let's use SIGNED numbers for this calculation.
1958
1959	IF some RANDOM number is GREATER than another RANDOM number...
1960	oh, let's BEGIN by setting the value of COUNT EQUAL to POSITIVE 17.
1961	also, let's COLORIZE this somewhat. set the red factor to 255;
1962	the green one to 0. also, leave the blue factor at 0. that should
1963	END the result of this condition.
1964
1965	OTHERWISE, just make COUNT EQUAL NEGATIVE 17.
1966
1967Did I mention ANY language? Even those that do not fit in to the old ASCII
1968character set? French? Slovak? Russian? Arabic? Japanese? Persian?
1969
1970Yep! Gracula will accept any character greater than 127 (maximum ASCII value)
1971and treat it as an acceptable character for any unquoted text string. This
1972allows you to enter text like the one above in any of the ISO 8859 series
1973of standards. It also allows you to write your script in Unicode. You may
1974encode your Unicode text into UTF-8. Gracula will accept it without complaints.
1975The only catch is you still have to put some GCL commands in your text. :-)
1976
1977Don't have what it takes to convert to UTF-8? Just use my i18ntools. If you are
1978a FreeBSD user, just type:
1979
1980	cd /usr/ports/converters/i18ntools
1981	make install
1982
1983Everyone else can download the tools from http://www.whizkidtech.net/i18n/
1984and use their makefiles to build them.
1985
1986USING GRACULA AS UNIX FILTER
1987============================
1988
1989Please note carefully that GCL stands for Graphic Counter Language. It is NOT
1990a WEB counter language. Of course, it can be used on the web. But it can also
1991be used in ANY application that requires a graphic counter or timer.
1992
1993When no GCL script is specified, gracula reads the script from stdin, and
1994compiles to stdout. Of course, if you use the -n switch (or the nocompile
1995directive), it will not compile.
1996
1997Suppose you want to write an X application to display current time graphically.
1998You could simply create a loop where you run code like this once a second:
1999
2000	gcl = popen("/usr/local/bin/gracula -lnmaz", "r+");
2001	fprintf(gcl, gclscript);
2002	i = 0;
2003	while((c = fgetc(gcl)) != EOF)
2004		gif[i++] = c;
2005	pclose(gcl);
2006	displaygif(gif, i);
2007
2008Here we assume that displaygif() is a function you have written to display
2009a gif image from a buffer, and that it expects to receive a pointer to the
2010buffer and the number of bytes in the buffer. Also we assume that gclscript
2011is a text string containing some GCL script.
2012
2013We have used the `-l' option to prevent gracula from outputting an HTTP
2014header, and the `-n' option to stop it from outputting a compiled version
2015of the script. The `-maz' options will produce a timer displaying current
2016date, time, and time zone.
2017
2018Alternately, in a counter, you can decide not to use the `-n' switch and let
2019gracula tell you the next value of count. In that case, you need to separate
2020the compiled script from the gif. This is easy because the last line of the
2021compiled script will contain "count = nnnn" where nnnn is an integer.
2022
2023This line will end with a newline character, after which the data of the GIF
2024file will follow.
2025
2026Note that if you use the `-p' switch, the compiled output will NOT end with
2027the count, but it will not create a GIF image either. There is generally
2028no reason to use the `-p' switch when popening gracula.
2029
2030Please make sure to abide by the license whenever distributing gracula with
2031other programs. You will find its terms very favorable. I will be pleased if
2032you let me know that you are using gracula with your program. You can email
2033me to gcl@whizkidtech.net.
2034
2035COMMAND LINE OPTIONS
2036====================
2037
2038Again, this is just an incomplete overview. Read the web site and the mailing
2039list for others.
2040
2041	-k (make) allows you to create your own defaults. Gracula will
2042	   read your GCL file and produce gcldefaults.h and gcldefaults.c
2043	   files. You then recompile gracula, and voila, your defaults
2044	   (including images) are built in.
2045
2046	   If you ever need to port your GCL files to a system with
2047	   different defaults, append the `portable' keyword to your
2048	   script. Normally, gracula does not write defaults into the
2049	   script when compiling it. This is to save time. However,
2050	   with the `portable' keyword, it will write everything in.
2051
2052	   Once you have ported your script to a system with different
2053	   defaults, you can append `portable none' to it. Gracula will,
2054	   once again, produces smaller compiled scripts.
2055
2056	-p (publish) allows you to share your scripts with others.
2057	   It will produce a nice, commented, script and send it to
2058	   stdout. Hint: Set the GCLAUTHOR environment variable to
2059	   your name. The published script will then contain your
2060	   copyright.
2061
2062	-g (gallery) will produce gif output containing all your
2063	   images. This is useful to show off what a script can do.
2064	   It is also useful as a quick diagnostic: If you made any
2065	   mistakes, you will see them instantly.
2066
2067	-i (inhibit) will recompile the script but not increase the
2068	   value of the counter.
2069
2070	-t (text) will produce a text counter/timer which can be
2071	   included in SSI.
2072
2073	-l (local) will NOT produce any HTTP header, just the gif
2074	   or text output.
2075
2076	-o (omit grouping) will NOT divide the counter intro groups
2077	   separated by commas, dots, or spaces.
2078
2079	-a (date) will show current date instead of a counter.
2080
2081	-m (time) will show current time instead of a counter.
2082
2083	-z (zone) will show the letter `Z' if used with the `utc'
2084	   directive without an offset in seconds, or the time
2085	   offset in +/-hh:mm:ss otherwise. Typically combined
2086	   with -a and -m.
2087
2088	-h (help) shows all command line options.
2089
2090Well, this is just an overview of some of the features of GCL and gracula.
2091I sure hope I whetted your appetite. See you on my website and on the gracula
2092mailing list. Again, you can subscribe to it at
2093
2094	http://www.onelist.com/subscribe/gracula
2095
2096