f0a93afec85256d31db6bb222eaabd163474cc48
[cacao.git] / src / vm / global.h
1 /* global.h ********************************************************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         Contains global definitions which are used in the whole program, includes
8         some files and contains global used macros.
9
10         Authors: Reinhard Grafl              EMAIL: cacao@complang.tuwien.ac.at
11                  Andreas  Krall   (andi)     EMAIL: cacao@complang.tuwien.ac.at
12         Changes: Mark     Probst  (schani)   EMAIL: cacao@complang.tuwien.ac.at
13                          Philipp  Tomsich (phil)     EMAIL: cacao@complang.tuwien.ac.at
14
15         Last Change: $Id: global.h 466 2003-09-25 07:55:50Z carolyn $
16
17 *******************************************************************************/
18
19 #ifndef __global_h_
20 #define __global_h_
21
22 #include "config.h"
23
24 #define NEW_GC              /* if enabled, includes the new gc. -- phil.      */
25
26 #define STATISTICS          /* if enabled collects program statistics         */
27
28 /* 
29  * JIT_MARKER_SUPPORT is the define used to toggle Just-in-time generated
30  * marker functions on and off.
31  *
32  * SIZE_FROM_CLASSINFO toggles between the bitmap_based and the new method 
33  * of determining the sizes of objects on the heap.
34  */
35 #undef JIT_MARKER_SUPPORT        /* phil */
36 #define SIZE_FROM_CLASSINFO
37
38 /* standard includes **********************************************************/
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <time.h>
44
45 #include "toolbox/memory.h"
46 #include "toolbox/chain.h"
47 #include "toolbox/list.h"
48 #include "toolbox/loging.h"
49
50 /* system dependent types *****************************************************/
51
52 #include "types.h"
53
54
55 /* additional data types ******************************************************/
56
57 typedef void *voidptr;          /* generic pointer */
58
59 typedef int   bool;             /* boolean data type */
60
61 #define true  1
62 #define false 0
63
64 #define PRIMITIVETYPE_COUNT  9  /* number of primitive types */
65
66 typedef void (*functionptr) (); /* generic function pointer */
67
68
69 #define MAX_ALIGN 8             /* most generic alignment for JavaVM values   */
70
71 /* shutdown function **********************************************************/
72
73 void cacao_shutdown(s4 status);
74
75
76 /* basic data types ***********************************************************/
77
78 #define TYPE_INT      0         /* the JavaVM types must numbered in the      */
79 #define TYPE_LONG     1         /* same order as the ICMD_Ixxx to ICMD_Axxx   */
80 #define TYPE_FLOAT    2         /* instructions (LOAD and STORE)              */
81 #define TYPE_DOUBLE   3         /* integer, long, float, double, address      */
82 #define TYPE_ADDRESS  4         /* all other types can be numbered arbitrarly */
83
84 #define TYPE_VOID    10
85
86
87 /* Java class file constants **************************************************/
88
89 #define MAGIC         0xcafebabe
90 #define MINOR_VERSION 3
91 #define MAJOR_VERSION 45
92
93 #define CONSTANT_Class                 7
94 #define CONSTANT_Fieldref              9
95 #define CONSTANT_Methodref            10
96 #define CONSTANT_InterfaceMethodref   11
97 #define CONSTANT_String                8
98 #define CONSTANT_Integer               3
99 #define CONSTANT_Float                 4
100 #define CONSTANT_Long                  5
101 #define CONSTANT_Double                6
102 #define CONSTANT_NameAndType          12
103 #define CONSTANT_Utf8                  1
104
105 #define CONSTANT_Arraydescriptor      13
106 #define CONSTANT_UNUSED                0
107
108 #define ACC_PUBLIC                0x0001
109 #define ACC_PRIVATE               0x0002
110 #define ACC_PROTECTED             0x0004
111 #define ACC_STATIC                0x0008
112 #define ACC_FINAL                 0x0010
113 #define ACC_SYNCHRONIZED          0x0020
114 #define ACC_VOLATILE              0x0040
115 #define ACC_TRANSIENT             0x0080
116 #define ACC_NATIVE                0x0100
117 #define ACC_INTERFACE             0x0200
118 #define ACC_ABSTRACT              0x0400
119
120
121 /* resolve typedef cycles *****************************************************/
122
123 typedef struct utf utf;
124 typedef struct literalstring literalstring;
125 typedef struct java_objectheader java_objectheader; 
126 typedef struct classinfo classinfo; 
127 typedef struct vftbl vftbl;
128 typedef u1* methodptr;
129
130
131 /* constant pool entries *******************************************************
132
133         All constant pool entries need a data structure which contain the entrys
134         value. In some cases this structure exist already, in the remaining cases
135         this structure must be generated:
136
137                 kind                      structure                     generated?
138         ----------------------------------------------------------------------
139     CONSTANT_Class               classinfo                           no
140     CONSTANT_Fieldref            constant_FMIref                    yes
141     CONSTANT_Methodref           constant_FMIref                    yes
142     CONSTANT_InterfaceMethodref  constant_FMIref                    yes
143     CONSTANT_String              unicode                             no
144     CONSTANT_Integer             constant_integer                   yes
145     CONSTANT_Float               constant_float                     yes
146     CONSTANT_Long                constant_long                      yes
147     CONSTANT_Double              constant_double                    yes
148     CONSTANT_NameAndType         constant_nameandtype               yes
149     CONSTANT_Utf8                unicode                             no
150     CONSTANT_Arraydescriptor     constant_arraydescriptor           yes
151     CONSTANT_UNUSED              -
152
153 *******************************************************************************/
154
155 /* data structures for hashtables ********************************************
156
157
158         All utf-symbols, javastrings and classes are stored in global hashtables,
159         so every symbol exists only once. Equal symbols have identical pointers.
160         The functions for adding hashtable elements search the table for the 
161         element with the specified name/text and return it on success. Otherwise a 
162         new hashtable element is created.
163
164     The hashtables use external linking for handling collisions. The hashtable 
165         structure contains a pointer <ptr> to the array of hashtable slots. The 
166         number of hashtable slots and therefore the size of this array is specified 
167         by the element <size> of hashtable structure. <entries> contains the number
168         of all hashtable elements stored in the table, including those in the 
169         external chains.
170         The hashtable element structures (utf, literalstring, classinfo) contain
171         both a pointer to the next hashtable element as a link for the external hash 
172         chain and the key of the element. The key is computed from the text of
173         the string or the classname by using up to 8 characters.
174         
175         If the number of entries in the hashtable exceeds twice the size of the 
176         hashtableslot-array it is supposed that the average length of the 
177         external chains has reached a value beyond 2. Therefore the functions for
178         adding hashtable elements (utf_new, class_new, literalstring_new) double
179         the hashtableslot-array. In this restructuring process all elements have
180         to be inserted into the new hashtable and new external chains must be built.
181
182
183 example for the layout of a hashtable:
184
185 hashtable.ptr-->  +-------------------+
186                   |                   |
187                            ...
188                   |                   |
189                   +-------------------+   +-------------------+   +-------------------+
190                   | hashtable element |-->| hashtable element |-->| hashtable element |-->NULL
191                   +-------------------+   +-------------------+   +-------------------+
192                   | hashtable element |
193                   +-------------------+   +-------------------+   
194                   | hashtable element |-->| hashtable element |-->NULL
195                   +-------------------+   +-------------------+   
196                   | hashtable element |-->NULL
197                   +-------------------+
198                   |                   |
199                            ...
200                   |                   |
201                   +-------------------+
202
203 */
204
205
206 /* data structure for utf8 symbols ********************************************/
207
208 struct utf {
209         utf        *hashlink;       /* link for external hash chain               */
210         int         blength;        /* text length in bytes                       */           
211         char       *text;           /* pointer to text                            */
212 };
213
214 /* data structure of internal javastrings stored in global hashtable **********/
215
216 struct literalstring {
217         literalstring     *hashlink;     /* link for external hash chain          */
218         java_objectheader *string;  
219 };
220
221 /* data structure for accessing hashtables ************************************/
222
223 typedef struct {            
224   u4 size;
225   u4 entries;        /* number of entries in the table */
226   void **ptr;        /* pointer to hashtable */
227 } hashtable;
228
229 /* data structures of remaining constant pool entries *************************/
230
231 typedef struct {                /* Fieldref, Methodref and InterfaceMethodref     */
232         classinfo *class;       /* class containing this field/method/interface   */
233         utf       *name;        /* field/method/interface name                    */
234         utf       *descriptor;  /* field/method/interface type descriptor string  */
235 } constant_FMIref;
236
237 typedef struct {            /* Integer                                        */
238         s4 value;
239 } constant_integer;
240         
241 typedef struct {            /* Float                                          */
242         float value;
243 } constant_float;
244
245 typedef struct {            /* Long                                           */
246         s8 value;
247 } constant_long;
248         
249 typedef struct {            /* Double                                         */
250         double value;
251 } constant_double;
252
253 typedef struct {            /* NameAndType (Field or Method)                  */
254         utf *name;              /* field/method name                              */
255         utf *descriptor;        /* field/method type descriptor string            */
256 } constant_nameandtype;
257
258 /*  arraydescriptor describes array types. Basic array types contain their
259         type in the arraytype field, objectclass contains a class pointer for
260         arrays of objects (arraytype == ARRAYTYPE_OBJECT), elementdescriptor
261         contains a pointer to an arraydescriptor which describes the element
262         types in the case of arrays of arrays (arraytype == ARRAYTYPE_ARRAY).
263 */
264
265 typedef struct constant_arraydescriptor {
266         int arraytype;
267         classinfo *objectclass;
268         struct constant_arraydescriptor *elementdescriptor;
269 } constant_arraydescriptor;
270
271
272 /* data structures of the runtime system **************************************/
273
274 /* objects *********************************************************************
275
276         All objects (and arrays) which resides on the heap need the following
277         header at the beginning of the data structure.
278 */
279
280 struct java_objectheader {              /* header for all objects             */
281         vftbl *vftbl;                       /* pointer to virtual function table  */
282 };
283
284
285
286 /* arrays **********************************************************************
287
288         All arrays are objects (they need the object header with a pointer to a
289         vvftbl (array class table). There is only one class for all arrays. The
290         type of an array is stored directly in the array object. Following types
291         are defined:
292 */
293
294 #define ARRAYTYPE_INT      0
295 #define ARRAYTYPE_LONG     1
296 #define ARRAYTYPE_FLOAT    2
297 #define ARRAYTYPE_DOUBLE   3
298 #define ARRAYTYPE_BYTE     4
299 #define ARRAYTYPE_CHAR     5
300 #define ARRAYTYPE_SHORT    6
301 #define ARRAYTYPE_BOOLEAN  7
302 #define ARRAYTYPE_OBJECT   8
303 #define ARRAYTYPE_ARRAY    9
304
305 typedef struct java_arrayheader {       /* header for all arrays              */
306         java_objectheader objheader;        /* object header                      */
307         s4 size;                            /* array size                         */
308 #ifdef SIZE_FROM_CLASSINFO
309         s4 alignedsize; /* phil */
310 #endif
311         s4 arraytype;                       /* array type from previous list      */
312 } java_arrayheader;
313
314
315
316 /* structs for all kinds of arrays ********************************************/
317
318 typedef struct java_chararray {
319         java_arrayheader header;
320         u2 data[1];
321 } java_chararray;
322
323 typedef struct java_floatheader {
324         java_arrayheader header;
325         float data[1];
326 } java_floatarray;
327
328 typedef struct java_doublearray {
329         java_arrayheader header;
330         double data[1];
331 } java_doublearray;
332
333 /*  booleanarray and bytearray need identical memory layout (access methods
334     use the same machine code */
335
336 typedef struct java_booleanarray {
337         java_arrayheader header;
338         u1 data[1];
339 } java_booleanarray;
340
341 typedef struct java_bytearray {
342         java_arrayheader header;
343         s1 data[1];
344 } java_bytearray;
345
346 typedef struct java_shortarray {
347         java_arrayheader header;
348         s2 data[1];
349 } java_shortarray;
350
351 typedef struct java_intarray {
352         java_arrayheader header;
353         s4 data[1];
354 } java_intarray;
355
356 typedef struct java_longarray {
357         java_arrayheader header;
358         s8 data[1];
359 } java_longarray;
360
361 /*  objectarray and arrayarray need identical memory layout (access methods
362     use the same machine code */
363
364 typedef struct java_objectarray {
365         java_arrayheader header;
366         classinfo *elementtype;
367         java_objectheader *data[1];
368 } java_objectarray;
369
370 typedef struct java_arrayarray {
371         java_arrayheader header;
372         constant_arraydescriptor *elementdescriptor;
373         java_arrayheader *data[1];
374 } java_arrayarray;
375
376
377 /* structure for primitive classes ********************************************/
378
379 typedef struct primitivetypeinfo {
380         classinfo *class_wrap;               /* class for wrapping primitive type */
381         classinfo *class_primitive;          /* primitive class                   */
382         char *wrapname;                      /* name of class for wrapping        */
383         char typesig;                        /* one character type signature      */
384         char *name;                          /* name of primitive class           */
385 } primitivetypeinfo;
386
387 /* field, method and class structures *****************************************/
388
389 /* fieldinfo ******************************************************************/
390
391 typedef struct fieldinfo {/* field of a class                                 */
392         s4       flags;       /* ACC flags                                        */
393         s4       type;        /* basic data type                                  */
394         utf *name;            /* name of field                                    */
395         utf *descriptor;      /* JavaVM descriptor string of field                */
396         
397         s4       offset;      /* offset from start of object (instance variables) */
398
399         union {               /* storage for static values (class variables)      */
400                 s4 i; 
401                 s8 l;
402                 float f;
403                 double d;
404                 void *a; 
405         } value;
406
407 } fieldinfo;
408
409 struct basicblock;
410
411 /* exceptiontable *************************************************************/
412
413 typedef struct xtable { /* exceptiontable entry in a method           */ 
414         s4         startpc;         /* start pc of guarded area (inclusive)       */
415         struct basicblock *start;
416
417         s4         endpc;           /* end pc of guarded area (exklusive)         */
418         struct basicblock *end;
419
420         s4         handlerpc;       /* pc of exception handler                    */
421         struct basicblock *handler;
422
423         classinfo *catchtype;       /* catchtype of exception (NULL == catchall)  */
424         struct xtable *next;        /* used to build a list of exception when     */
425                                     /* loops are copied */
426         struct xtable *down;        /* instead of the old array, a list is used   */
427 } xtable;
428
429
430 typedef struct exceptiontable { /* exceptiontable entry in a method           */ 
431         s4         startpc;         /* start pc of guarded area (inclusive)       */
432         s4         endpc;           /* end pc of guarded area (exklusive)         */
433         s4         handlerpc;       /* pc of exception handler                    */
434         classinfo *catchtype;       /* catchtype of exception (NULL == catchall)  */
435 } exceptiontable;
436
437
438 /* methodinfo *****************************************************************/
439
440 typedef struct methodinfo {         /* method structure                       */
441         s4             flags;               /* ACC flags                              */
442         utf       *name;                /* name of method                         */
443         utf       *descriptor;          /* JavaVM descriptor string of method     */
444         s4         returntype;          /* only temporary valid, return type      */
445         s4         paramcount;          /* only temporary valid, parameter count  */
446         u1        *paramtypes;          /* only temporary valid, parameter types  */
447         classinfo *class;               /* class, the method belongs to           */
448         s4         vftblindex;          /* index of method in virtual function table
449                                            (if it is a virtual method)            */
450         s4         maxstack;            /* maximum stack depth of method          */
451         s4         maxlocals;           /* maximum number of local variables      */
452         s4         jcodelength;         /* length of JavaVM code                  */
453         u1        *jcode;               /* pointer to JavaVM code                 */
454
455         s4         exceptiontablelength;/* exceptiontable length                  */
456         exceptiontable *exceptiontable; 
457                                     /* the exceptiontable                     */
458
459         u1        *stubroutine;         /* stub for compiling or calling natives  */    
460         s4         mcodelength;         /* legth of generated machine code        */
461         u1        *mcode;               /* pointer to machine code                */
462         u1        *entrypoint;          /* entry point in machine code            */
463
464         s4        methodUsed;           /* -1=marked (might be used) 0=not used 1=used CO-RT*/
465         s4        numSubDefs;           /* # sub definitions marked USED          */
466
467         s4          natCalls;           /* number of methods  calls               */
468         
469         s4          XTAclasscount;     /* number of classes in XTA class set       */
470         classinfo   *XTAclassSet;       /* XTA class set*/
471
472
473 } methodinfo;
474
475
476 /* innerclassinfo *************************************************************/
477
478 typedef struct innerclassinfo {
479         classinfo *inner_class;       /* inner class pointer                      */
480         classinfo *outer_class;       /* outer class pointer                      */
481         utf *name;                    /* innerclass name                          */ 
482         s4 flags;                     /* ACC flags                                */
483 } innerclassinfo;
484
485 /* classinfo ******************************************************************/
486
487 struct classinfo {                /* class structure                          */
488         java_objectheader header;     /* classes are also objects                 */
489
490         s4          flags;            /* ACC flags                                */
491         utf        *name;             /* class name                               */ 
492
493         s4          cpcount;          /* number of entries in constant pool       */
494         u1         *cptags;           /* constant pool tags                       */
495         voidptr    *cpinfos;          /* pointer to constant pool info structures */
496
497         classinfo  *super;            /* super class pointer                      */
498         classinfo  *sub;              /* sub class pointer                        */
499         classinfo  *nextsub;          /* pointer to next class in sub class list  */
500
501         s4          interfacescount;  /* number of interfaces                     */
502         classinfo **interfaces;       /* pointer to interfaces                    */
503
504         s4          fieldscount;      /* number of fields                         */
505         fieldinfo  *fields;           /* field table                              */
506
507         s4          methodscount;     /* number of methods                        */
508         methodinfo *methods;          /* method table                             */
509
510         listnode    listnode;         /* linkage                                  */
511
512         bool        initialized;      /* true, if class already initialised       */ 
513         bool        linked;           /* true, if class already linked            */
514         s4          index;            /* hierarchy depth (classes) or index
515                                          (interfaces)                             */ 
516         s4          instancesize;     /* size of an instance of this class        */
517 #ifdef SIZE_FROM_CLASSINFO
518         s4          alignedsize;      /* size of an instance, aligned to the 
519                                                                          allocation size on the heap */
520 #endif
521
522         vftbl      *vftbl;            /* pointer to virtual function table        */
523
524         methodinfo *finalizer;        /* finalizer method                         */
525 #ifdef JIT_MARKER_SUPPORT
526         methodinfo *marker; 
527 #endif
528
529     u2             innerclasscount;   /* number of inner classes              */
530     innerclassinfo *innerclass;
531
532     classinfo      *hashlink;         /* link for external hash chain         */
533         bool        classvftbl;       /* has its own copy of the Class vtbl       */
534
535         s4          classUsed;        /* 0= not used 1 = used   CO-RT             */
536
537         classinfo  *impldBy;          /* implemented by class pointer             */
538         classinfo  *nextimpldBy;      /* ptr to next class in impldBy class list  */
539
540 };
541
542
543 /* virtual function table ******************************************************
544
545         The vtbl has a bidirectional layout with open ends at both sides.
546         interfacetablelength gives the number of entries of the interface table at
547         the start of the vftbl. The vftbl pointer points to &interfacetable[0].
548         vftbllength gives the number of entries of table at the end of the vftbl.
549
550         runtime type check (checkcast):
551
552         Different methods are used for runtime type check depending on the
553         argument of checkcast/instanceof.
554         
555         A check against a class is implemented via relative numbering on the class
556         hierachy tree. The tree is numbered in a depth first traversal setting
557         the base field and the diff field. The diff field gets the result of
558         (high - base) so that a range check can be implemented by an unsigned
559         compare. A sub type test is done by checking the inclusion of base of
560         the sub class in the range of the superclass.
561
562         A check against an interface is implemented via the interfacevftbl. If the
563         interfacevftbl contains a nonnull value a class is a subclass of this
564         interface.
565
566         interfacetable:
567
568         Like standard virtual methods interface methods are called using
569         virtual function tables. All interfaces are numbered sequentially
570         (starting with zero). For each class there exist an interface table
571         of virtual function tables for each implemented interface. The length
572         of the interface table is determined by the highest number of an
573         implemented interface.
574
575         The following example assumes a class which implements interface 0 and 3:
576
577         interfacetablelength = 4
578
579                   | ...       |            +----------+
580                       +-----------+            | method 2 |---> method z
581                       | class     |            | method 1 |---> method y
582                       +-----------+            | method 0 |---> method x
583                       | ivftbl  0 |----------> +----------+
584         vftblptr ---> +-----------+
585                   | ivftbl -1 |--> NULL    +----------+
586                   | ivftbl -2 |--> NULL    | method 1 |---> method x
587                   | ivftbl -3 |-----+      | method 0 |---> method a
588                   +-----------+     +----> +----------+
589      
590                               +---------------+
591                                   | length 3 = 2  |
592                                   | length 2 = 0  |
593                                   | length 1 = 0  |
594                                   | length 0 = 3  |
595         interfacevftbllength ---> +---------------+
596
597 *******************************************************************************/
598
599 struct vftbl {
600         methodptr   *interfacetable[1];    /* interface table (access via macro)  */
601
602         classinfo   *class;                /* class, the vtbl belongs to          */
603
604         s4           vftbllength;          /* virtual function table length       */
605         s4           interfacetablelength; /* interface table length              */
606
607         s4           baseval;              /* base for runtime type check         */
608         s4           diffval;              /* high - base for runtime type check  */
609
610         s4          *interfacevftbllength; /* length of interface vftbls          */
611         
612         methodptr    table[1];             /* class vftbl                         */
613 };
614
615 #define VFTBLINTERFACETABLE(v,i)       (v)->interfacetable[-i]
616
617
618 /* references to some system classes ******************************************/
619
620 extern classinfo *class_java_lang_Object;
621 extern classinfo *class_java_lang_String;
622 extern classinfo *class_java_lang_ClassCastException;
623 extern classinfo *class_java_lang_NullPointerException;
624 extern classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
625 extern classinfo *class_java_lang_NegativeArraySizeException;
626 extern classinfo *class_java_lang_OutOfMemoryError;
627 extern classinfo *class_java_lang_ArithmeticException;
628 extern classinfo *class_java_lang_ArrayStoreException;
629 extern classinfo *class_java_lang_ThreadDeath;
630 extern classinfo *class_array;
631
632 /* instances of some system classes *******************************************/
633
634 extern java_objectheader *proto_java_lang_ClassCastException;
635 extern java_objectheader *proto_java_lang_NullPointerException;
636 extern java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
637 extern java_objectheader *proto_java_lang_NegativeArraySizeException;
638 extern java_objectheader *proto_java_lang_OutOfMemoryError;
639 extern java_objectheader *proto_java_lang_ArithmeticException;
640 extern java_objectheader *proto_java_lang_ArrayStoreException;
641 extern java_objectheader *proto_java_lang_ThreadDeath;
642
643
644 /* flag variables *************************************************************/
645
646 extern bool compileall;
647 extern bool runverbose;         
648 extern bool verbose;         
649 extern bool opt_rt;             /* Rapid Type Analysis for better inlining CO-RT*/
650 extern bool opt_xta;            /* X Type Analysis for better inlining    CO-XTA*/
651
652 extern int pClassHeir;
653 extern int pCallgraph;
654 extern int pOpcodes;
655 extern int pStats;
656
657 extern void RT_jit_parse(methodinfo *m);
658 extern void printCallgraph ();
659 extern void printRThierarchyInfo(methodinfo *m);
660 extern void printObjectClassHeirarchy();
661
662 extern void XTA_jit_parse(methodinfo *m);
663
664 /* statistic variables ********************************************************/
665
666 extern int count_class_infos;
667 extern int count_const_pool_len;
668 extern int count_vftbl_len;
669 extern int count_utf_len;
670 extern int count_all_methods;
671 extern int count_vmcode_len;
672 extern int count_extable_len;
673 extern int count_class_loads;
674 extern int count_class_inits;
675 extern int count_utf_new;
676 extern int count_utf_new_found;
677
678 /* table of primitive types ***************************************************/
679
680 extern primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT];
681
682 #endif
683
684
685 /*
686  * These are local overrides for various environment variables in Emacs.
687  * Please do not remove this and leave it at the end of the file, where
688  * Emacs will automagically detect them.
689  * ---------------------------------------------------------------------
690  * Local variables:
691  * mode: c
692  * indent-tabs-mode: t
693  * c-basic-offset: 4
694  * tab-width: 4
695  * End:
696  */