* src/vm/global.h (ACC_CLASS_MEMBER): New define.
[cacao.git] / src / native / vm / java_lang_Class.c
1 /* src/native/vm/java_lang_Class.c - java/lang/Class
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: java_lang_Class.c 8339 2007-08-17 21:21:51Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <string.h>
35
36 #include "vm/types.h"
37
38 #include "mm/memory.h"
39
40 #include "native/jni.h"
41 #include "native/llni.h"
42 #include "native/native.h"
43
44 /* keep this order of the native includes */
45
46 #include "native/include/java_lang_String.h"
47
48 #if defined(ENABLE_JAVASE)
49 # if defined(WITH_CLASSPATH_SUN)
50 #  include "native/include/java_nio_ByteBuffer.h"       /* required by j.l.CL */
51 # endif
52 # include "native/include/java_lang_ClassLoader.h"
53 #endif
54
55 #include "native/include/java_lang_Object.h"
56 #include "native/include/java_lang_Class.h"
57
58 #if defined(ENABLE_JAVASE)
59 # include "native/include/java_lang_reflect_Constructor.h"
60 # include "native/include/java_lang_reflect_Field.h"
61 # include "native/include/java_lang_reflect_Method.h"
62 #endif
63
64 #include "native/vm/java_lang_Class.h"
65 #include "native/vm/java_lang_String.h"
66
67 #if defined(ENABLE_JAVASE)
68 # include "native/vm/reflect.h"
69 #endif
70
71 #include "toolbox/logging.h"
72
73 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/initialize.h"
77 #include "vm/primitive.h"
78 #include "vm/resolve.h"
79 #include "vm/stringlocal.h"
80
81 #include "vmcore/class.h"
82 #include "vmcore/loader.h"
83
84 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
85 #include "vm/vm.h"
86 #include "vmcore/annotation.h"
87 #include "native/include/sun_reflect_ConstantPool.h"
88 #endif
89
90 /*
91  * Class:     java/lang/Class
92  * Method:    getName
93  * Signature: ()Ljava/lang/String;
94  */
95 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
96 {
97         classinfo        *c;
98         java_lang_String *s;
99         java_chararray_t *ca;
100         u4                i;
101
102         c = (classinfo *) klass;
103
104         /* create a java string */
105
106         s = (java_lang_String *) javastring_new(c->name);
107
108         if (s == NULL)
109                 return NULL;
110
111         /* return string where '/' is replaced by '.' */
112
113         LLNI_field_get_ref(s, value, ca);
114
115         for (i = 0; i < LLNI_array_size(ca); i++) {
116                 if (LLNI_array_direct(ca, i) == '/')
117                         LLNI_array_direct(ca, i) = '.';
118         }
119
120         return s;
121 }
122
123
124 /*
125  * Class:     java/lang/Class
126  * Method:    forName
127  * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
128  */
129 #if defined(ENABLE_JAVASE)
130 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
131 #elif defined(ENABLE_JAVAME_CLDC1_1)
132 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
133 #endif
134 {
135 #if defined(ENABLE_JAVASE)
136         classloader *cl;
137 #endif
138         utf         *ufile;
139         utf         *uname;
140         classinfo   *c;
141         u2          *pos;
142         s4           i;
143
144 #if defined(ENABLE_JAVASE)
145         cl = (classloader *) loader;
146 #endif
147
148         /* illegal argument */
149
150         if (name == NULL) {
151                 exceptions_throw_nullpointerexception();
152                 return NULL;
153         }
154
155         /* create utf string in which '.' is replaced by '/' */
156
157         ufile = javastring_toutf((java_handle_t *) name, true);
158         uname = javastring_toutf((java_handle_t *) name, false);
159
160         /* name must not contain '/' (mauve test) */
161
162         for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
163                 if (*pos == '/') {
164                         exceptions_throw_classnotfoundexception(uname);
165                         return NULL;
166                 }
167         }
168
169         /* try to load, ... */
170
171 #if defined(ENABLE_JAVASE)
172         c = load_class_from_classloader(ufile, cl);
173 #elif defined(ENABLE_JAVAME_CLDC1_1)
174         c = load_class_bootstrap(ufile);
175 #endif
176
177         if (c == NULL)
178             return NULL;
179
180         /* link, ... */
181
182         if (!link_class(c))
183                 return NULL;
184         
185         /* ...and initialize it, if required */
186
187 #if defined(ENABLE_JAVASE)
188         if (initialize)
189 #endif
190                 if (!initialize_class(c))
191                         return NULL;
192
193         return (java_lang_Class *) c;
194 }
195
196
197 /*
198  * Class:     java/lang/Class
199  * Method:    isInstance
200  * Signature: (Ljava/lang/Object;)Z
201  */
202 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
203 {
204         classinfo     *c;
205         java_handle_t *ob;
206
207         c = (classinfo *) klass;
208         ob = (java_handle_t *) o;
209
210         if (!(c->state & CLASS_LINKED))
211                 if (!link_class(c))
212                         return 0;
213
214         return builtin_instanceof(ob, c);
215 }
216
217
218 /*
219  * Class:     java/lang/Class
220  * Method:    isAssignableFrom
221  * Signature: (Ljava/lang/Class;)Z
222  */
223 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
224 {
225         classinfo *kc;
226         classinfo *cc;
227
228         kc = (classinfo *) klass;
229         cc = (classinfo *) c;
230
231         if (cc == NULL) {
232                 exceptions_throw_nullpointerexception();
233                 return 0;
234         }
235
236         if (!(kc->state & CLASS_LINKED))
237                 if (!link_class(kc))
238                         return 0;
239
240         if (!(cc->state & CLASS_LINKED))
241                 if (!link_class(cc))
242                         return 0;
243
244         return class_isanysubclass(cc, kc);
245 }
246
247
248 /*
249  * Class:     java/lang/Class
250  * Method:    isInterface
251  * Signature: ()Z
252  */
253 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isInterface(JNIEnv *env, java_lang_Class *this)
254 {
255         classinfo *c;
256
257         c = (classinfo *) this;
258
259         return class_is_interface(c);
260 }
261
262
263 #if defined(ENABLE_JAVASE)
264
265 /*
266  * Class:     java/lang/Class
267  * Method:    isPrimitive
268  * Signature: ()Z
269  */
270 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
271 {
272         classinfo *c;
273
274         c = (classinfo *) klass;
275
276         return class_is_primitive(c);
277 }
278
279
280 /*
281  * Class:     java/lang/Class
282  * Method:    getSuperclass
283  * Signature: ()Ljava/lang/Class;
284  */
285 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
286 {
287         classinfo *c;
288         classinfo *super;
289
290         c = (classinfo *) klass;
291
292         super = class_get_superclass(c);
293
294         return (java_lang_Class *) super;
295 }
296
297
298 /*
299  * Class:     java/lang/Class
300  * Method:    getInterfaces
301  * Signature: ()[Ljava/lang/Class;
302  */
303 java_handle_objectarray_t *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
304 {
305         classinfo                 *c;
306         java_handle_objectarray_t *oa;
307
308         c = (classinfo *) klass;
309
310         oa = class_get_interfaces(c);
311
312         return oa;
313 }
314
315
316 /*
317  * Class:     java/lang/Class
318  * Method:    getModifiers
319  * Signature: (Z)I
320  */
321 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
322 {
323         classinfo             *c;
324         classref_or_classinfo  inner;
325         classref_or_classinfo  outer;
326         utf                   *innername;
327         s4                     i;
328
329         c = (classinfo *) klass;
330
331         if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
332                 /* search for passed class as inner class */
333
334                 for (i = 0; i < c->innerclasscount; i++) {
335                         inner = c->innerclass[i].inner_class;
336                         outer = c->innerclass[i].outer_class;
337
338                         /* Check if inner is a classref or a real class and get
339                the name of the structure */
340
341                         innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
342
343                         /* innerclass is this class */
344
345                         if (innername == c->name) {
346                                 /* has the class actually an outer class? */
347
348                                 if (outer.any)
349                                         /* return flags got from the outer class file */
350                                         return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
351                                 else
352                                         return c->flags & ACC_CLASS_REFLECT_MASK;
353                         }
354                 }
355         }
356
357         /* passed class is no inner class or it was not requested */
358
359         return c->flags & ACC_CLASS_REFLECT_MASK;
360 }
361
362
363 /*
364  * Class:     java/lang/Class
365  * Method:    getDeclaringClass
366  * Signature: ()Ljava/lang/Class;
367  */
368 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
369 {
370         classinfo *c;
371
372         c = (classinfo *) klass;
373
374         return (java_lang_Class *) class_get_declaringclass(c);
375 }
376
377
378 /*
379  * Class:     java/lang/Class
380  * Method:    getDeclaredClasses
381  * Signature: (Z)[Ljava/lang/Class;
382  */
383 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
384 {
385         classinfo                 *c;
386         java_handle_objectarray_t *oa;
387
388         c = (classinfo *) klass;
389
390         oa = class_get_declaredclasses(c, publicOnly);
391
392         return oa;
393 }
394
395
396 /*
397  * Class:     java/lang/Class
398  * Method:    getDeclaredFields
399  * Signature: (Z)[Ljava/lang/reflect/Field;
400  */
401 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
402 {
403         classinfo                 *c;
404         java_handle_objectarray_t *oa;          /* result: array of field-objects */
405         fieldinfo                 *f;
406         java_lang_reflect_Field   *rf;
407         s4 public_fields;                    /* number of elements in field-array */
408         s4 pos;
409         s4 i;
410
411         c = (classinfo *) klass;
412
413         /* determine number of fields */
414
415         for (i = 0, public_fields = 0; i < c->fieldscount; i++)
416                 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
417                         public_fields++;
418
419         /* create array of fields */
420
421         oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
422
423         if (oa == NULL)
424                 return NULL;
425
426         /* get the fields and store in the array */
427
428         for (i = 0, pos = 0; i < c->fieldscount; i++) {
429                 f = &(c->fields[i]);
430
431                 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
432                         /* create Field object */
433
434                         rf = reflect_field_new(f);
435
436                         /* store object into array */
437
438                         LLNI_objectarray_element_set(oa, pos, rf);
439                         pos++;
440                 }
441         }
442
443         return oa;
444 }
445
446
447 /*
448  * Class:     java/lang/Class
449  * Method:    getDeclaredMethods
450  * Signature: (Z)[Ljava/lang/reflect/Method;
451  */
452 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
453 {
454         classinfo                 *c;
455         java_lang_reflect_Method  *rm;
456         java_handle_objectarray_t *oa;         /* result: array of Method-objects */
457         methodinfo                *m;     /* the current method to be represented */
458         s4 public_methods;               /* number of public methods of the class */
459         s4 pos;
460         s4 i;
461
462         c = (classinfo *) klass;
463
464         public_methods = 0;
465
466         /* JOWENN: array classes do not declare methods according to mauve
467            test.  It should be considered, if we should return to my old
468            clone method overriding instead of declaring it as a member
469            function. */
470
471         if (class_is_array(c))
472                 return builtin_anewarray(0, class_java_lang_reflect_Method);
473
474         /* determine number of methods */
475
476         for (i = 0; i < c->methodscount; i++) {
477                 m = &c->methods[i];
478
479                 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
480                         ((m->name != utf_init) && (m->name != utf_clinit)) &&
481                         !(m->flags & ACC_MIRANDA))
482                         public_methods++;
483         }
484
485         oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
486
487         if (oa == NULL)
488                 return NULL;
489
490         for (i = 0, pos = 0; i < c->methodscount; i++) {
491                 m = &c->methods[i];
492
493                 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) && 
494                         ((m->name != utf_init) && (m->name != utf_clinit)) &&
495                         !(m->flags & ACC_MIRANDA)) {
496                         /* create Method object */
497
498                         rm = reflect_method_new(m);
499
500                         /* store object into array */
501
502                         LLNI_objectarray_element_set(oa, pos, rm);
503                         pos++;
504                 }
505         }
506
507         return oa;
508 }
509
510
511 /*
512  * Class:     java/lang/Class
513  * Method:    getDeclaredConstructors
514  * Signature: (Z)[Ljava/lang/reflect/Constructor;
515  */
516 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
517 {
518         classinfo                     *c;
519         methodinfo                    *m; /* the current method to be represented */
520         java_handle_objectarray_t     *oa;     /* result: array of Method-objects */
521         java_lang_reflect_Constructor *rc;
522         s4 public_methods;               /* number of public methods of the class */
523         s4 pos;
524         s4 i;
525
526         c = (classinfo *) klass;
527
528         /* determine number of constructors */
529
530         for (i = 0, public_methods = 0; i < c->methodscount; i++) {
531                 m = &c->methods[i];
532
533                 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
534                         (m->name == utf_init))
535                         public_methods++;
536         }
537
538         oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
539
540         if (oa == NULL)
541                 return NULL;
542
543         for (i = 0, pos = 0; i < c->methodscount; i++) {
544                 m = &c->methods[i];
545
546                 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
547                         (m->name == utf_init)) {
548                         /* create Constructor object */
549
550                         rc = reflect_constructor_new(m);
551
552                         /* store object into array */
553
554                         LLNI_objectarray_element_set(oa, pos, rc);
555                         pos++;
556                 }
557         }
558
559         return oa;
560 }
561
562
563 /*
564  * Class:     java/lang/Class
565  * Method:    getClassLoader
566  * Signature: ()Ljava/lang/ClassLoader;
567  */
568 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
569 {
570         classinfo *c;
571
572         c = (classinfo *) klass;
573
574         return (java_lang_ClassLoader *) c->classloader;
575 }
576
577 #endif /* defined(ENABLE_JAVASE) */
578
579
580 /*
581  * Class:     java/lang/Class
582  * Method:    isArray
583  * Signature: ()Z
584  */
585 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
586 {
587         classinfo *c;
588
589         c = (classinfo *) this;
590
591         return class_is_array(c);
592 }
593
594
595 #if defined(ENABLE_JAVASE)
596
597 /*
598  * Class:     java/lang/Class
599  * Method:    throwException
600  * Signature: (Ljava/lang/Throwable;)V
601  */
602 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
603 {
604         java_handle_t *o;
605
606         o = (java_handle_t *) t;
607
608         exceptions_set_exception(o);
609 }
610
611
612 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
613 /*
614  * Class:     java/lang/Class
615  * Method:    getDeclaredAnnotations
616  * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
617  */
618 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
619 {
620         classinfo                *c               = (classinfo*)klass;
621         static methodinfo        *m_parseAnnotationsIntoArray   = NULL;
622         utf                      *utf_parseAnnotationsIntoArray = NULL;
623         utf                      *utf_desc        = NULL;
624         java_handle_bytearray_t  *annotations     = NULL;
625         sun_reflect_ConstantPool *constantPool    = NULL;
626         uint32_t                  size            = 0;
627         java_lang_Object         *constantPoolOop = (java_lang_Object*)klass;
628
629         if (c == NULL) {
630                 exceptions_throw_nullpointerexception();
631                 return NULL;
632         }
633         
634         /* Return null for arrays and primitives: */
635         if (class_is_primitive(c) || class_is_array(c)) {
636                 return NULL;
637         }
638
639         if (c->annotations != NULL) {
640                 size        = c->annotations->size;
641                 annotations = builtin_newarray_byte(size);
642
643                 if(annotations != NULL) {
644                         MCOPY(annotations->data, c->annotations->data, uint8_t, size);
645                 }
646         }
647
648         constantPool = 
649                 (sun_reflect_ConstantPool*)native_new_and_init(
650                         class_sun_reflect_ConstantPool);
651         
652         if(constantPool == NULL) {
653                 /* out of memory */
654                 return NULL;
655         }
656
657         LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
658
659         /* only resolve the method the first time */
660         if (m_parseAnnotationsIntoArray == NULL) {
661                 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
662                 utf_desc = utf_new_char(
663                         "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
664                         "[Ljava/lang/annotation/Annotation;");
665
666                 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
667                         /* out of memory */
668                         return NULL;
669                 }
670
671                 m_parseAnnotationsIntoArray = class_resolveclassmethod(
672                         class_sun_reflect_annotation_AnnotationParser,
673                         utf_parseAnnotationsIntoArray,
674                         utf_desc,
675                         class_java_lang_Class,
676                         true);
677
678                 if (m_parseAnnotationsIntoArray == NULL) {
679                         /* method not found */
680                         return NULL;
681                 }
682         }
683
684         return (java_handle_objectarray_t*)vm_call_method(
685                 m_parseAnnotationsIntoArray, NULL,
686                 annotations, constantPool, klass);
687 }
688 #endif
689
690
691 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
692
693    Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
694    _Jv_java_lang_Class_getEnclosingMethod.
695
696 *******************************************************************************/
697
698 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
699 {
700         constant_nameandtype *cn;
701         classinfo            *ec;
702         methodinfo           *m;
703
704         /* get enclosing class and method */
705
706         ec = class_get_enclosingclass(c);
707         cn = c->enclosingmethod;
708
709         /* check for enclosing class and method */
710
711         if (ec == NULL)
712                 return NULL;
713
714         if (cn == NULL)
715                 return NULL;
716
717         /* find method in enclosing class */
718
719         m = class_findmethod(ec, cn->name, cn->descriptor);
720
721         if (m == NULL) {
722                 exceptions_throw_internalerror("Enclosing method doesn't exist");
723                 return NULL;
724         }
725
726         return m;
727 }
728
729
730 /*
731  * Class:     java/lang/Class
732  * Method:    getEnclosingConstructor
733  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
734  */
735 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
736 {
737         classinfo                     *c;
738         methodinfo                    *m;
739         java_lang_reflect_Constructor *rc;
740
741         c = (classinfo *) klass;
742
743         /* get enclosing method */
744
745         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
746
747         if (m == NULL)
748                 return NULL;
749
750         /* check for <init> */
751
752         if (m->name != utf_init)
753                 return NULL;
754
755         /* create Constructor object */
756
757         rc = reflect_constructor_new(m);
758
759         return rc;
760 }
761
762
763 /*
764  * Class:     java/lang/Class
765  * Method:    getEnclosingMethod
766  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
767  */
768 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
769 {
770         classinfo                *c;
771         methodinfo               *m;
772         java_lang_reflect_Method *rm;
773
774         c = (classinfo *) klass;
775
776         /* get enclosing method */
777
778         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
779
780         if (m == NULL)
781                 return NULL;
782
783         /* check for <init> */
784
785         if (m->name == utf_init)
786                 return NULL;
787
788         /* create java.lang.reflect.Method object */
789
790         rm = reflect_method_new(m);
791
792         return rm;
793 }
794
795
796 /*
797  * Class:     java/lang/Class
798  * Method:    getClassSignature
799  * Signature: (Ljava/lang/Class;)Ljava/lang/String;
800  */
801 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
802 {
803         classinfo     *c;
804         java_handle_t *o;
805
806         c = (classinfo *) klass;
807
808         if (c->signature == NULL)
809                 return NULL;
810
811         o = javastring_new(c->signature);
812
813         /* in error case o is NULL */
814
815         return (java_lang_String *) o;
816 }
817
818 #endif /* ENABLE_JAVASE */
819
820
821 /*
822  * These are local overrides for various environment variables in Emacs.
823  * Please do not remove this and leave it at the end of the file, where
824  * Emacs will automagically detect them.
825  * ---------------------------------------------------------------------
826  * Local variables:
827  * mode: c
828  * indent-tabs-mode: t
829  * c-basic-offset: 4
830  * tab-width: 4
831  * End:
832  * vim:noexpandtab:sw=4:ts=4:
833  */