1 /*
2  * gracula 3.0
3  *
4  * Graphic Counter Language
5  *
6  * Header file
7  *
8  * Copyright 1999 G. Adam Stanislav
9  * All rights reserved
10  *
11  * Started:	11-Jan-1999
12  * Updated:	18-Jun-1999
13  *
14  */
15 #ifndef	GCL_H
16 #define	GCL_H
17 
18 #define	GCLRELEASEVERSION	"3.0"
19 #define	GCLVERSION	GCLRELEASEVERSION
20 
21 #include "gd.h"
22 
23 #ifdef	GCLUSEC9X
24 typedef	unsigned long long	counter_t;
25 typedef	long long		scounter_t;
26 #define	strtoul			strtoull
27 #define	atoi(s)			strtoll(s, (char **)NULL, 10)
28 #define	integer			"%llu"
29 #define	sinteger		"%lli"
30 #define	counteger		"%0*llu"
31 #define scounteger		"%0*lli"
32 #else
33 #ifdef	GCLUSELONGLONG
34 typedef	unsigned long long	counter_t;
35 typedef	long long		scounter_t;
36 #define	strtoul			strtouq
37 #define	atoi(s)			strtoq(s, (char **)NULL, 10)
38 #define	integer			"%qu"
39 #define	sinteger		"%qi"
40 #define	counteger		"%0*qu"
41 #define	scounteger		"%0*qi"
42 #else
43 typedef	unsigned long		counter_t;
44 typedef	long			scounter_t;
45 #define	integer			"%lu"
46 #define	sinteger		"%li"
47 #define	counteger		"%0*lu"
48 #define	scounteger		"%0*li"
49 #endif	/* GCLUSELONGLONG */
50 #endif	/* GCLUSEC9X */
51 
52 /*
53  * You may change these if you need larger strings, or more digits or inhibitors.
54  * However, please do not distribute this file if you change it!
55  */
56 #define	LBSIZE	1024	/* lexbuffer size */
57 #define	MAXDIGITS	127	/* Maximum number of digits in the counter */
58 
59 #define	ACCEPTABLECHARS	25
60 #define	SECONDSINAYEAR	(60 * 60 * 24 * 365)
61 
62 /* lexanal return values */
63 enum {
64 	GCLPATH = 256,
65 	GCLGRAPHICNUMBER,
66 	BACKGROUND,
67 	INVIS,
68 	TRANSPARENT,
69 	EXPIRES,
70 	TOKALIGN,
71 	SHIFT,
72 	FRAME,
73 	FRAMETYPE,
74 	VERTICAL,
75 	HORIZONTAL,
76 	KERN,
77 	PAD,
78 	MINDIGITS,
79 	OPTIMIZE,
80 	SECURE,
81 	COOKIE,
82 	INHIBITOR,
83 	RELAYOR,
84 	TEXTCHAR,
85 	TEDTURNER,
86 	SILENT,
87 	REDIRECT,
88 	TODAY,
89 	PER,
90 	TIMEZONE,
91 	SECONDS,
92 	FORK,
93 	PORTABLEGCL,
94 	GROUP,
95 	GCLREVERSE,
96 	GCLPRINT,
97 	NOCOMPILE,
98 	SIGNEDCOUNTER,
99 	UNSIGNEDCOUNTER,
100 	FILEINCLUDE,
101 	GCLREGISTER,
102 	GCLINCREMENT,
103 	GCLFUDGE,
104 	GCLSIGMA,
105 	GCLPUSH,
106 	AK,
107 	TRI,
108 
109 	TAK,
110 	INAK,
111 	ADD,
112 	INC,
113 	SUB,
114 	DEC,
115 	BAND,
116 	BOR,
117 	MUL,
118 	DIV,
119 	MOD,
120 	XOR,
121 	NE,
122 	EQU,
123 	GE,
124 	LE,
125 	CMP,
126 	SHR,
127 	SHL,
128 	LAND,
129 	LXOR,
130 	LOR,
131 	PASSIGN,
132 	INTEGER,
133 	STRING,
134 	GCLENV,
135 	PICTYPE,
136 	HSHIFT,
137 	VSHIFT,
138 	VALIGN,
139 	HALIGN,
140 	NONE,
141 	TOPBOTTOM,
142 	COUNTER,
143 	FROM,
144 	SHELL,
145 	REFERRER,
146 	CONDITION,
147 	TIMEPERIOD,
148 	NODEFAULT,
149 	USEDEFAULT,
150 	GCLERROR
151 };
152 
153 /* GCL registers and variables */
154 enum {
155 	REGA,
156 	REGB,
157 	REGC,
158 	REGD,
159 	/*
160 	 * By inserting variables into this array we can use the same section
161 	 * of code to manipulate variables as we do for registers.
162 	 */
163 	COUNT,
164 	NUMREGS
165 };
166 
167 #define	count	gclregs[COUNT]
168 
169 /* How often do we reset? */
170 typedef enum {
171 	WEEKLY = -1,
172 	NEVER,
173 	ANNUALY,
174 	MONTHLY,
175 	DAILY
176 } gclreset;
177 
178 typedef enum {
179 	STZ,	/* Server Time Zone */
180 	UTC		/* Universal Time Coordinated, p.k.a. GMT */
181 } gcltzone;
182 
183 #define	SHOWCOUNT	0
184 #define	SHOWTIME	1
185 #define	SHOWDATE	2
186 #define	SHOWZONE	4
187 
188 #define	monthfirst(x)	((x) < 0)
189 #define	yearfirst(x)	((x) == 0)
190 #define	dayfirst(x)	((x) > 0)
191 
192 #define	VPAD	TOPBOTTOM
193 #define	HPAD	HSHIFT
194 
195 /* pad index */
196 enum {
197 	TPAD,
198 	BPAD,
199 	LPAD,
200 	RPAD,
201 	NUMPADS
202 };
203 
204 #define	tpad	pad[TPAD]
205 #define	bpad	pad[BPAD]
206 #define	lpad	pad[LPAD]
207 #define	rpad	pad[RPAD]
208 
209 /* frame types */
210 enum {
211 	POPUP = 1,
212 	BUTTON,
213 	DEFAULTBUTTON,
214 	SHADOW,
215 	BOX,
216 	FRAMES	/* number of frame types */
217 };
218 
219 /* graphic array indices */
220 enum {
221 	DASH = 10,
222 	COLON,
223 	TIME,
224 	ZONE,
225 	MINUS,
226 	PLUS,
227 	SPACE,
228 	DOT,
229 	COMMA,
230 	HEADPICTURE,
231 	TAILPICTURE,
232 	/* keep the above in their place! */
233 	BKGPICTURE,
234 	TILE,
235 	ARRAYPICTURE,
236 	PICTUREDIRECTORY,
237 	GRAPHICS
238 };
239 
240 #define	arraypicture	(picture[ARRAYPICTURE])
241 #define	picturedirectory	(picture[PICTUREDIRECTORY])
242 #define	spacepicture	(picture[SPACE])
243 #define	dotpicture	(picture[DOT])
244 #define	commapicture	(picture[COMMA])
245 #define	bkgpicture	(picture[BKGPICTURE])
246 #define	headpicture	(picture[HEADPICTURE])
247 #define	tailpicture	(picture[TAILPICTURE])
248 #define tilepicture	(picture[TILE])
249 #define	dashpicture	(picture[DASH])
250 #define	colonpicture	(picture[COLON])
251 #define	pluspicture	(picture[PLUS])
252 #define	minuspicture	(picture[MINUS])
253 #define	timepicture	(picture[TIME])
254 #define	zonepicture	(picture[ZONE])
255 #define	tileimage	(defaultimage[TILE])
256 #define	bkgimage	(defaultimage[BKGPICTURE])
257 
258 enum {
259 	DEFINECOMMA,
260 	DEFINECOLON,
261 	DEFINEDASH,
262 	DEFINETIME,
263 	DEFINEZONE,
264 	DEFINECHAR
265 };
266 
267 #define	comma	(definechar[DEFINECOMMA])
268 #define	colon	(definechar[DEFINECOLON])
269 #define	dash	(definechar[DEFINEDASH])
270 #define	timechar	(definechar[DEFINETIME])
271 #define	zone	(definechar[DEFINEZONE])
272 
273 /* types of graphics in the counter layer */
274 enum {
275 	/* Keep HEAD at position 0 */
276 	HEAD,
277 	TAIL,
278 	DIGITS,
279 	COMMAS,
280 	SPACES,
281 	DOTS,
282 	DASHES,
283 	COLONS,
284 	PLUSSES,
285 	MINUSES,
286 	TIMES,
287 	ZONES,
288 	GRAPHICTYPES
289 };
290 
291 /*
292  * Note on "ternary" logic:
293  *
294  * GCL often uses logic that can have three states. Traditional
295  * computer logic uses two states (e.g. FALSE and TRUE) with values
296  * of zero and non-zero (binary logic).
297  *
298  * For anything else, C programs typically use "enum" which by default
299  * starts at zero. Whenever there are three possible states (quite often
300  * in this program), GCL uses "enum" but overrides the default values
301  * to start at -1 instead of zero. This compiles to three values: -1, 0, 1.
302  *
303  * The advantage of this approach is that we can check the logic as being
304  * less than zero, equal to zero, or greater than zero, as opposed to
305  * equal to zero, equal to 1, equal to 2. In other words, the resultant
306  * machine code only needs to make ONE comparison instead of three, then branch
307  * off based on whether it is less than, equal to, or greater than, the compared
308  * value. The gcc compiler understands this and produces highly optimized
309  * code (at least with the -O3 switch).
310  *
311  * As I was writing the program, at first I used #define to declare the values
312  * of -1, 0, 1, and hardcoded the comparisons in the program. Later, I was
313  * using ternary logic in more and more places, and started using enums, as
314  * well as placed the comparisons into this header file as macros. This,
315  * hopefully, makes the code easier to read, and it certainly makes it easier
316  * to maintain.
317  *
318  * But you will find some remnants of the original approach of using #define
319  * rather than enum here. In either case, the resultant machine code should
320  * be exactly the same regardless of which approach is used.
321  *
322  * In some cases, (such as "when" and "unless") I ended up using binary
323  * logic after all but did not change the enum to two states only. It makes
324  * no difference in the efficiency of the resultant code, while trying to
325  * change it might have easily introduced bugs. And who needs those?
326  */
327 
328 /* redirection ternary logic */
329 typedef enum {
330 	UNINHIBITEDREDIRECTION = -1,
331 	NOREDIRECTION,
332 	REDIRECTORINHIBIT
333 } gclredirection;
334 
335 #define	uninhibitedredirection(x)	((int)(x) < 0)
336 #define	noredirection(x)	((int)(x) == 0)
337 #define	redirectorinhibit(x)	((int)(x) > 0)
338 
339 /* alignment/shift types */
340 #define	TOP	(-1)
341 #define	MIDDLE	0
342 #define	BOTTOM	1
343 #define	LEFT	(-1)
344 #define	CENTER	0
345 #define	RIGHT	1
346 #define	UP	(-1)
347 #define	DOWN	1
348 
349 /* transparency permissions */
350 #define	TRANSREQUIRED	(-1)
351 #define	NOTRANS	0
352 #define	TRANSOK	1
353 #define	transrequired(b)	(b.trans < 0)
354 #define	notrans(b)	(b.trans == 0)
355 #define	transok(b)	(b.trans > 0)
356 
357 /* image file types */
358 #define	GIFSOURCE	1
359 #define	GDSOURCE	2
360 #define	XBMSOURCE	3
361 
362 /* ternary conditions */
363 typedef enum {
364 	UNLESS = -1,
365 	NOCONDITION,
366 	WHEN
367 } gclcondition;
368 
369 #define	unless(x)	((x) < 0)
370 #define	when(x)	((x) > 0)
371 
372 typedef struct {
373 	int h[GRAPHICTYPES];
374 	int v[GRAPHICTYPES];
375 } gclalign;
376 
377 #define	halignflag	(alignflag.h)
378 #define	valignflag	(alignflag.v)
379 #define	hashift	(ashift.h)
380 #define	vashift	(ashift.v)
381 
382 typedef struct {
383 	char *graphic;
384 	gdImagePtr image;
385 	int gtype;
386 	int origin;
387 	int isused:1;
388 	int isarray:1;
389 	int iscreated:1;
390 	int x, y, dx, dy;
391 } gclpic;
392 
393 typedef struct {
394 	int left;
395 	int top;
396 	int right;
397 	int bottom;
398 	int trans;
399 	void (*draw)(gdImagePtr, int, int, int, int);
400 } gclframe;
401 
402 typedef	struct {
403 	int red;
404 	int green;
405 	int blue;
406 } rgbcolor;
407 
408 typedef enum {
409 	CONCEDE,
410 	INHIBIT
411 } gclinhibitor;
412 
413 typedef struct inhibit {
414 	int op;
415 	gclcondition condition;
416 	gclinhibitor inhibitor;
417 	char *env;
418 	char *val;
419 	int cookie;
420 	struct inhibit *next;
421 } inhibit;
422 
423 typedef enum {
424 	SERVE,
425 	RELAY
426 } gclrelayor;
427 
428 typedef struct relay {
429 	int op;
430 	gclcondition condition;
431 	gclrelayor relayor;
432 	char *env;
433 	char *val;
434 	int cookie;
435 	struct relay *next;
436 	char *url;
437 } relay;
438 
439 typedef struct {
440 	char *name;
441 	char *value;
442 } cookiepair;
443 
444 typedef struct {
445 	int year;
446 	int month;
447 	int day;
448 	int week;
449 } gcldate;
450 
451 typedef struct {
452 	gcltzone tz;
453 	long secs;
454 } gcltimezone;
455 
456 typedef struct fi {
457 	FILE *fh;
458 	struct fi *prev;
459 	int lineno;
460 	char *filename;
461 } fi;
462 
463 /*
464  * Random number generator constants. These are redefinable on the C compiler
465  * command line: Still searching for the perfect ones...
466  */
467 #ifndef	GCLRNDMUL
468 #define	GCLRNDMUL	11093
469 #elif	GCLRNDMUL <= 0
470 #undef	GCLRNDMUL
471 #define	GCLRNDMUL	11093
472 #endif
473 #ifndef	GCLRNDADD
474 #define	GCLRNDADD	2099711
475 #elif	GCLRNDADD <= 0
476 #undef	GCLRNDADD
477 #define	GCLRNDADD	2099711
478 #endif
479 
480 /*
481  * I guess it would make sense to call unputlex "ungetlex" as it is
482  * modeled after "ungetc" but for some unexplained reason I just
483  * happened to type "put" instead of "get" when I first started working
484  * on this. There is no subtle reason for the use of "put" except that
485  * I was probably thinking about a thousand other things when I first
486  * defined the macro, and did not feel later on there was any good
487  * reason to change it.
488  */
489 #define	unputlex(c)	lexstack=(c)
490 #define	token(t,v)	if (!strcmp(lexbuffer,t)) return (v)
491 #define	lvtoken(t,l,v)	if (!strcmp(lexbuffer,t)) {lexvalue=(l);return(v);}
492 #define	lex	(l=lexanal())
493 #define	signedinteger	l=expression()
494 #define	synterr(str)	syntax(str);unputlex(l);break
495 #define polite(str)	if (!syschat(str)){chars=0;continue;}
496 #endif	/* GCL_H */
497