1 /* src/vm/exceptions.c - exception related functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Thalinger
29 Changes: Edwin Steiner
31 $Id: exceptions.c 4128 2006-01-10 20:57:18Z twisti $
45 #include "mm/memory.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_String.h"
48 #include "native/include/java_lang_Throwable.h"
49 #include "toolbox/logging.h"
50 #include "toolbox/util.h"
52 #include "vm/exceptions.h"
53 #include "vm/global.h"
54 #include "vm/loader.h"
55 #include "vm/options.h"
56 #include "vm/stringlocal.h"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/jit.h"
59 #include "vm/jit/methodheader.h"
62 /* for raising exceptions from native methods *********************************/
64 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
65 java_objectheader *_no_threads_exceptionptr = NULL;
69 /* init_system_exceptions ******************************************************
71 Load and link exceptions used in the system.
73 *******************************************************************************/
75 bool exceptions_init(void)
77 /* java/lang/Throwable */
79 if (!(class_java_lang_Throwable =
80 load_class_bootstrap(utf_java_lang_Throwable)) ||
81 !link_class(class_java_lang_Throwable))
85 /* java/lang/VMThrowable */
87 if (!(class_java_lang_VMThrowable =
88 load_class_bootstrap(utf_java_lang_VMThrowable)) ||
89 !link_class(class_java_lang_VMThrowable))
95 if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
96 !link_class(class_java_lang_Error))
99 /* java/lang/NoClassDefFoundError */
101 if (!(class_java_lang_NoClassDefFoundError =
102 load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
103 !link_class(class_java_lang_NoClassDefFoundError))
106 /* java/lang/LinkageError */
108 if (!(class_java_lang_LinkageError =
109 load_class_bootstrap(utf_java_lang_LinkageError)) ||
110 !link_class(class_java_lang_LinkageError))
113 /* java/lang/NoSuchMethodError */
115 if (!(class_java_lang_NoSuchMethodError =
116 load_class_bootstrap(utf_java_lang_NoSuchMethodError)) ||
117 !link_class(class_java_lang_NoSuchMethodError))
120 /* java/lang/OutOfMemoryError */
122 if (!(class_java_lang_OutOfMemoryError =
123 load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
124 !link_class(class_java_lang_OutOfMemoryError))
128 /* java/lang/Exception */
130 if (!(class_java_lang_Exception =
131 load_class_bootstrap(utf_java_lang_Exception)) ||
132 !link_class(class_java_lang_Exception))
135 /* java/lang/ClassNotFoundException */
137 if (!(class_java_lang_ClassNotFoundException =
138 load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
139 !link_class(class_java_lang_ClassNotFoundException))
142 /* java/lang/IllegalArgumentException */
144 if (!(class_java_lang_IllegalArgumentException =
145 load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
146 !link_class(class_java_lang_IllegalArgumentException))
149 /* java/lang/IllegalMonitorStateException */
151 if (!(class_java_lang_IllegalMonitorStateException =
152 load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
153 !link_class(class_java_lang_IllegalMonitorStateException))
156 /* java/lang/NullPointerException */
158 if (!(class_java_lang_NullPointerException =
159 load_class_bootstrap(utf_java_lang_NullPointerException)) ||
160 !link_class(class_java_lang_NullPointerException))
168 static void throw_exception_exit_intern(bool doexit)
170 java_objectheader *xptr;
174 xptr = *exceptionptr;
177 /* clear exception, because we are calling jit code again */
178 *exceptionptr = NULL;
180 c = xptr->vftbl->class;
182 pss = class_resolveclassmethod(c,
185 class_java_lang_Object,
188 /* print the stacktrace */
190 asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
192 /* This normally means, we are EXTREMLY out of memory or have a */
193 /* serious problem while printStackTrace. But may be another */
194 /* exception, so print it. */
197 java_lang_Throwable *t;
199 t = (java_lang_Throwable *) *exceptionptr;
201 fprintf(stderr, "Exception while printStackTrace(): ");
202 utf_fprint_classname(stderr, t->header.vftbl->class->name);
204 if (t->detailMessage) {
207 buf = javastring_tochar((java_objectheader *) t->detailMessage);
208 fprintf(stderr, ": %s", buf);
209 MFREE(buf, char, strlen(buf));
212 fprintf(stderr, "\n");
216 utf_fprint_classname(stderr, c->name);
217 fprintf(stderr, ": printStackTrace()V not found!\n");
230 void throw_exception(void)
232 throw_exception_exit_intern(false);
236 void throw_exception_exit(void)
238 throw_exception_exit_intern(true);
242 void throw_main_exception(void)
244 fprintf(stderr, "Exception in thread \"main\" ");
247 throw_exception_exit_intern(false);
251 void throw_main_exception_exit(void)
253 fprintf(stderr, "Exception in thread \"main\" ");
256 throw_exception_exit_intern(true);
260 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
267 len = strlen(exception);
268 tmp = MNEW(char, len + 1);
269 strncpy(tmp, exception, len);
272 /* convert to classname */
274 for (i = len - 1; i >= 0; i--)
275 if (tmp[i] == '/') tmp[i] = '.';
277 fprintf(stderr, "Exception in thread \"main\" %s", tmp);
279 MFREE(tmp, char, len);
281 if (strlen(message) > 0) {
282 fprintf(stderr, ": ");
284 va_start(ap, message);
285 vfprintf(stderr, message, ap);
289 fprintf(stderr, "\n");
298 /* exceptions_throw_outofmemory_exit *******************************************
300 Just print an: java.lang.InternalError: Out of memory
302 *******************************************************************************/
304 void exceptions_throw_outofmemory_exit(void)
306 throw_cacao_exception_exit(string_java_lang_InternalError,
311 /* new_exception ***************************************************************
313 Creates an exception object with the given name and initalizes it.
315 *******************************************************************************/
317 java_objectheader *new_exception(const char *classname)
319 java_objectheader *o;
322 if (!(c = load_class_bootstrap(utf_new_char(classname))))
323 return *exceptionptr;
325 o = native_new_and_init(c);
328 return *exceptionptr;
334 /* new_exception_message *******************************************************
336 Creates an exception object with the given name and initalizes it
337 with the given char message.
339 *******************************************************************************/
341 java_objectheader *new_exception_message(const char *classname,
344 java_objectheader *o;
347 if (!(c = load_class_bootstrap(utf_new_char(classname))))
348 return *exceptionptr;
350 o = native_new_and_init_string(c, javastring_new_char(message));
353 return *exceptionptr;
359 /* new_exception_throwable *****************************************************
361 Creates an exception object with the given name and initalizes it
362 with the given java/lang/Throwable exception.
364 *******************************************************************************/
366 java_objectheader *new_exception_throwable(const char *classname,
367 java_lang_Throwable *throwable)
369 java_objectheader *o;
372 if (!(c = load_class_bootstrap(utf_new_char(classname))))
373 return *exceptionptr;
375 o = native_new_and_init_throwable(c, throwable);
378 return *exceptionptr;
384 /* new_exception_utfmessage ****************************************************
386 Creates an exception object with the given name and initalizes it
387 with the given utf message.
389 *******************************************************************************/
391 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
393 java_objectheader *o;
396 if (!(c = load_class_bootstrap(utf_new_char(classname))))
397 return *exceptionptr;
399 o = native_new_and_init_string(c, javastring_new(message));
402 return *exceptionptr;
408 /* new_exception_javastring ****************************************************
410 Creates an exception object with the given name and initalizes it
411 with the given java/lang/String message.
413 *******************************************************************************/
415 java_objectheader *new_exception_javastring(const char *classname,
416 java_lang_String *message)
418 java_objectheader *o;
421 if (!(c = load_class_bootstrap(utf_new_char(classname))))
422 return *exceptionptr;
424 o = native_new_and_init_string(c, message);
427 return *exceptionptr;
433 /* new_exception_int ***********************************************************
435 Creates an exception object with the given name and initalizes it
436 with the given int value.
438 *******************************************************************************/
440 java_objectheader *new_exception_int(const char *classname, s4 i)
442 java_objectheader *o;
445 if (!(c = load_class_bootstrap(utf_new_char(classname))))
446 return *exceptionptr;
448 o = native_new_and_init_int(c, i);
451 return *exceptionptr;
457 /* new_classformaterror ********************************************************
459 generates a java.lang.ClassFormatError for the classloader
461 *******************************************************************************/
463 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
465 java_objectheader *o;
470 /* calculate message length */
475 msglen += utf_strlen(c->name) + strlen(" (");
477 va_start(ap, message);
478 msglen += get_variable_message_length(message, ap);
482 msglen += strlen(")");
484 msglen += strlen("0");
486 /* allocate a buffer */
488 msg = MNEW(char, msglen);
490 /* print message into allocated buffer */
493 utf_sprint_classname(msg, c->name);
497 va_start(ap, message);
498 vsprintf(msg + strlen(msg), message, ap);
504 o = new_exception_message(string_java_lang_ClassFormatError, msg);
506 MFREE(msg, char, msglen);
512 /* exceptions_throw_classformaterror *******************************************
514 Generates a java.lang.ClassFormatError for the VM system throw it
517 *******************************************************************************/
519 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
523 va_start(ap, message);
524 *exceptionptr = new_classformaterror(c, message, ap);
529 /* new_classnotfoundexception **************************************************
531 Generates a java.lang.ClassNotFoundException for the classloader.
533 *******************************************************************************/
535 java_objectheader *new_classnotfoundexception(utf *name)
537 java_objectheader *o;
539 o = native_new_and_init_string(class_java_lang_ClassNotFoundException,
540 javastring_new(name));
543 return *exceptionptr;
549 /* new_noclassdeffounderror ****************************************************
551 Generates a java.lang.NoClassDefFoundError
553 *******************************************************************************/
555 java_objectheader *new_noclassdeffounderror(utf *name)
557 java_objectheader *o;
559 o = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
560 javastring_new(name));
563 return *exceptionptr;
569 /* classnotfoundexception_to_noclassdeffounderror ******************************
571 Check the *exceptionptr for a ClassNotFoundException. If it is one,
572 convert it to a NoClassDefFoundError.
574 *******************************************************************************/
576 void classnotfoundexception_to_noclassdeffounderror(void)
578 java_objectheader *xptr;
579 java_objectheader *cause;
583 cause = *exceptionptr;
585 /* convert ClassNotFoundException's to NoClassDefFoundError's */
587 if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
588 /* clear exception, because we are calling jit code again */
590 *exceptionptr = NULL;
592 /* create new error */
595 new_exception_javastring(string_java_lang_NoClassDefFoundError,
596 ((java_lang_Throwable *) cause)->detailMessage);
598 /* we had an exception while creating the error */
603 /* set new exception */
605 *exceptionptr = xptr;
610 /* new_internalerror ***********************************************************
612 Generates a java.lang.InternalError for the VM.
614 *******************************************************************************/
616 java_objectheader *new_internalerror(const char *message, ...)
618 java_objectheader *o;
623 /* calculate exception message length */
625 va_start(ap, message);
626 msglen = get_variable_message_length(message, ap);
629 /* allocate memory */
631 msg = MNEW(char, msglen);
633 /* generate message */
635 va_start(ap, message);
636 vsprintf(msg, message, ap);
639 /* create exception object */
641 o = new_exception_message(string_java_lang_InternalError, msg);
645 MFREE(msg, char, msglen);
651 /* exceptions_new_linkageerror *************************************************
653 Generates a java.lang.LinkageError with an error message.
654 If c != NULL, the name of c is appended to the error message.
656 *******************************************************************************/
658 java_objectheader *exceptions_new_linkageerror(const char *message,
661 java_objectheader *o;
665 /* calculate exception message length */
667 msglen = strlen(message) + 1;
669 msglen += utf_strlen(c->name);
672 /* allocate memory */
674 msg = MNEW(char, msglen);
676 /* generate message */
680 utf_strcat(msg, c->name);
683 o = native_new_and_init_string(class_java_lang_LinkageError,
684 javastring_new_char(msg));
688 MFREE(msg, char, msglen);
694 /* exceptions_new_nosuchmethoderror ********************************************
696 Generates a java.lang.NoSuchMethodError with an error message.
698 *******************************************************************************/
700 java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
701 utf *name, utf *desc)
703 java_objectheader *o;
707 /* calculate exception message length */
709 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
710 utf_strlen(desc) + strlen("0");
712 /* allocate memory */
714 msg = MNEW(char, msglen);
716 /* generate message */
718 utf_sprint(msg, c->name);
720 utf_strcat(msg, name);
721 utf_strcat(msg, desc);
723 o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
724 javastring_new_char(msg));
728 MFREE(msg, char, msglen);
734 /* new_unsupportedclassversionerror ********************************************
736 generates a java.lang.UnsupportedClassVersionError for the classloader
738 *******************************************************************************/
740 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
742 java_objectheader *o;
747 /* calculate exception message length */
749 msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
751 va_start(ap, message);
752 msglen += get_variable_message_length(message, ap);
755 /* allocate memory */
757 msg = MNEW(char, msglen);
759 /* generate message */
761 utf_sprint_classname(msg, c->name);
764 va_start(ap, message);
765 vsprintf(msg + strlen(msg), message, ap);
770 /* create exception object */
772 o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
777 MFREE(msg, char, msglen);
783 /* new_verifyerror *************************************************************
785 generates a java.lang.VerifyError for the jit compiler
787 *******************************************************************************/
789 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
791 java_objectheader *o;
796 useinlining = false; /* at least until sure inlining works with exceptions*/
798 /* calculate exception message length */
803 msglen = strlen("(class: ") + utf_strlen(m->class->name) +
804 strlen(", method: ") + utf_strlen(m->name) +
805 strlen(" signature: ") + utf_strlen(m->descriptor) +
806 strlen(") ") + strlen("0");
808 va_start(ap, message);
809 msglen += get_variable_message_length(message, ap);
812 /* allocate memory */
814 msg = MNEW(char, msglen);
816 /* generate message */
819 strcpy(msg, "(class: ");
820 utf_strcat(msg, m->class->name);
821 strcat(msg, ", method: ");
822 utf_strcat(msg, m->name);
823 strcat(msg, " signature: ");
824 utf_strcat(msg, m->descriptor);
828 va_start(ap, message);
829 vsprintf(msg + strlen(msg), message, ap);
832 /* create exception object */
834 o = new_exception_message(string_java_lang_VerifyError, msg);
838 MFREE(msg, char, msglen);
844 /* new_arithmeticexception *****************************************************
846 Generates a java.lang.ArithmeticException for the jit compiler.
848 *******************************************************************************/
850 java_objectheader *new_arithmeticexception(void)
852 java_objectheader *e;
854 e = new_exception_message(string_java_lang_ArithmeticException,
855 string_java_lang_ArithmeticException_message);
858 return *exceptionptr;
864 /* exceptions_new_arrayindexoutofboundsexception *******************************
866 Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
869 *******************************************************************************/
871 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
873 java_objectheader *e;
877 /* convert the index into a String, like Sun does */
879 m = class_resolveclassmethod(class_java_lang_String,
880 utf_new_char("valueOf"),
881 utf_new_char("(I)Ljava/lang/String;"),
882 class_java_lang_Object,
886 return *exceptionptr;
888 s = (java_lang_String *) asm_calljavafunction(m,
889 (void *) (ptrint) index,
895 return *exceptionptr;
897 e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
901 return *exceptionptr;
907 /* exceptions_throw_arrayindexoutofboundsexception *****************************
909 Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
912 *******************************************************************************/
914 void exceptions_throw_arrayindexoutofboundsexception(void)
916 java_objectheader *e;
918 e = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
927 /* new_arraystoreexception *****************************************************
929 generates a java.lang.ArrayStoreException for the jit compiler
931 *******************************************************************************/
933 java_objectheader *new_arraystoreexception(void)
935 java_objectheader *e;
937 e = new_exception(string_java_lang_ArrayStoreException);
938 /* e = native_new_and_init(class_java_lang_ArrayStoreException); */
941 return *exceptionptr;
947 /* new_classcastexception ******************************************************
949 generates a java.lang.ClassCastException for the jit compiler
951 *******************************************************************************/
953 java_objectheader *new_classcastexception(void)
955 java_objectheader *e;
957 e = new_exception(string_java_lang_ClassCastException);
960 return *exceptionptr;
966 /* exceptions_new_illegalargumentexception *************************************
968 Generates a java.lang.IllegalArgumentException for the VM system.
970 *******************************************************************************/
972 java_objectheader *new_illegalargumentexception(void)
974 java_objectheader *e;
976 e = native_new_and_init(class_java_lang_IllegalArgumentException);
979 return *exceptionptr;
985 /* exceptions_throw_illegalargumentexception ***********************************
987 Generates a java.lang.IllegalArgumentException for the VM system
988 and throw it in the VM system.
990 *******************************************************************************/
992 void exceptions_throw_illegalargumentexception(void)
994 *exceptionptr = new_illegalargumentexception();
998 /* new_illegalmonitorstateexception ********************************************
1000 Generates a java.lang.IllegalMonitorStateException for the VM
1003 *******************************************************************************/
1005 java_objectheader *new_illegalmonitorstateexception(void)
1007 java_objectheader *e;
1009 e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
1012 return *exceptionptr;
1018 /* exceptions_new_negativearraysizeexception ***********************************
1020 Generates a java.lang.NegativeArraySizeException for the VM system.
1022 *******************************************************************************/
1024 java_objectheader *new_negativearraysizeexception(void)
1026 java_objectheader *e;
1028 e = new_exception(string_java_lang_NegativeArraySizeException);
1031 return *exceptionptr;
1037 /* exceptions_throw_negativearraysizeexception *********************************
1039 Generates a java.lang.NegativeArraySizeException for the VM system.
1041 *******************************************************************************/
1043 void exceptions_throw_negativearraysizeexception(void)
1045 *exceptionptr = new_negativearraysizeexception();
1049 /* new_nullpointerexception ****************************************************
1051 generates a java.lang.NullPointerException for the jit compiler
1053 *******************************************************************************/
1055 java_objectheader *new_nullpointerexception(void)
1057 java_objectheader *e;
1059 e = native_new_and_init(class_java_lang_NullPointerException);
1062 return *exceptionptr;
1068 /* exceptions_throw_nullpointerexception ***************************************
1070 Generates a java.lang.NullPointerException for the VM system and
1071 throw it in the VM system.
1073 *******************************************************************************/
1075 void exceptions_throw_nullpointerexception(void)
1077 *exceptionptr = new_nullpointerexception();
1081 /* exceptions_handle_exception *************************************************
1085 *******************************************************************************/
1087 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1093 s4 exceptiontablelength;
1095 classref_or_classinfo cr;
1097 java_objectheader *o;
1099 /* get methodinfo pointer from method header */
1101 m = *((methodinfo **) (pv + MethodPointer));
1102 framesize = *((s4 *) (pv + FrameSize));
1103 issync = *((s4 *) (pv + IsSync));
1104 ex = (exceptionentry *) (pv + ExTableStart);
1105 exceptiontablelength = *((s4 *) (pv + ExTableSize));
1109 printf("exceptions_handle_exception(%p, %p, %p, %p): ", xptr, xpc, pv, sp);
1110 utf_display(m->class->name);
1112 utf_display(m->name);
1113 utf_display(m->descriptor);
1114 printf(", %d\n", exceptiontablelength);
1118 /* print exception trace */
1120 if (opt_verbose || runverbose || opt_verboseexception)
1121 builtin_trace_exception(xptr, m, xpc, 1);
1123 for (i = 0; i < exceptiontablelength; i++) {
1124 /* ATTENTION: keep this here, as we need to decrement the
1125 pointer before the loop executes! */
1129 /* is the xpc is the current catch range */
1131 if (ex->startpc <= xpc && xpc < ex->endpc) {
1134 /* NULL catches everything */
1137 return ex->handlerpc;
1139 /* resolve or load/link the exception class */
1141 if (IS_CLASSREF(cr)) {
1142 c = resolve_classref_eager(cr.ref);
1147 if (!(c->state & CLASS_LOADED))
1148 /* use the methods' classloader */
1149 if (!load_class_from_classloader(c->name,
1150 m->class->classloader))
1153 if (!(c->state & CLASS_LINKED))
1158 /* is the thrown exception an instance of the catch class? */
1160 if (builtin_instanceof(xptr, c))
1161 return ex->handlerpc;
1165 #if defined(USE_THREADS)
1166 /* is this method synchronized? */
1169 /* get synchronization object */
1171 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1172 /* XXX change this if we ever want to use 4-byte stackslots */
1173 o = *((java_objectheader **) (sp + issync - 8));
1175 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1180 builtin_monitorexit(o);
1184 /* none of the exceptions catch this one */
1190 /* exceptions_print_exception **************************************************
1192 Prints an exception, the detail message and the cause, if
1193 available, with CACAO internal functions to stdout.
1195 *******************************************************************************/
1197 #if !defined(NDEBUG)
1198 void exceptions_print_exception(java_objectheader *xptr)
1200 java_lang_Throwable *t;
1201 java_lang_Throwable *cause;
1204 t = (java_lang_Throwable *) xptr;
1207 /* print the root exception */
1209 utf_display_classname(t->header.vftbl->class->name);
1211 if (t->detailMessage) {
1212 u = javastring_toutf(t->detailMessage, false);
1220 /* print the cause if available */
1222 if (cause && (cause != t)) {
1223 printf("Caused by: ");
1224 utf_display_classname(cause->header.vftbl->class->name);
1226 if (cause->detailMessage) {
1227 u = javastring_toutf(cause->detailMessage, false);
1236 #endif /* !defined(NDEBUG) */
1240 * These are local overrides for various environment variables in Emacs.
1241 * Please do not remove this and leave it at the end of the file, where
1242 * Emacs will automagically detect them.
1243 * ---------------------------------------------------------------------
1246 * indent-tabs-mode: t