X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/d67594ff366291f164fb41e4dcc791494ec4bb0e..24f4b7dabc89e2f15420d419caa79471a92a6143:/perl.h diff --git a/perl.h b/perl.h index 30b8eb2..f4dc00e 100644 --- a/perl.h +++ b/perl.h @@ -48,15 +48,6 @@ * repeated in makedef.pl, so be certain to update * both places when editing. */ -#ifdef PERL_IMPLICIT_SYS -/* PERL_IMPLICIT_SYS implies PerlMemShared != PerlMem - so use slab allocator to avoid lots of MUTEX overhead - */ -# ifndef PL_OP_SLAB_ALLOC -# define PL_OP_SLAB_ALLOC -# endif -#endif - #ifdef USE_ITHREADS # if !defined(MULTIPLICITY) # define MULTIPLICITY @@ -359,7 +350,11 @@ /* Rats: if dTHR is just blank then the subsequent ";" throws an error */ /* Declaring a *function*, instead of a variable, ensures that we don't rely on being able to suppress "unused" warnings. */ +#ifdef __cplusplus +#define dNOOP (void)0 +#else #define dNOOP extern int Perl___notused(void) +#endif #ifndef pTHX /* Don't bother defining tTHX and sTHX; using them outside @@ -515,7 +510,7 @@ register struct op *Perl_op asm(stringify(OP_IN_REGISTER)); */ /* define this once if either system, instead of cluttering up the src */ -#if defined(MSDOS) || defined(atarist) || defined(WIN32) || defined(NETWARE) +#if defined(MSDOS) || defined(WIN32) || defined(NETWARE) #define DOSISH 1 #endif @@ -734,6 +729,8 @@ EXTERN_C int usleep(unsigned int); # define U64_CONST(x) ((U64)x##UL) # elif QUADKIND == QUAD_IS_LONG_LONG # define U64_CONST(x) ((U64)x##ULL) +# elif QUADKIND == QUAD_IS___INT64 +# define U64_CONST(x) ((U64)x##UI64) # else /* best guess we can make */ # define U64_CONST(x) ((U64)x##UL) # endif @@ -974,17 +971,6 @@ EXTERN_C int usleep(unsigned int); #define PERL_DEFAULT_DO_EXEC3_IMPLEMENTATION #endif -/* Cannot include embed.h here on Win32 as win32.h has not - yet been included and defines some config variables e.g. HAVE_INTERP_INTERN - */ -#if !defined(PERL_FOR_X2P) && !(defined(WIN32)||defined(VMS)) -# include "embed.h" -# ifndef PERL_MAD -# undef op_getmad -# define op_getmad(arg,pegop,slot) NOOP -# endif -#endif - #define MEM_SIZE Size_t /* Round all values passed to malloc up, by default to a multiple of @@ -1186,7 +1172,7 @@ EXTERN_C int usleep(unsigned int); # define S_IFIFO _S_IFIFO #endif -/* The stat macros for Amdahl UTS, Unisoft System V/88 (and derivatives +/* The stat macros for Unisoft System V/88 (and derivatives like UTekV) are broken, sometimes giving false positives. Undefine them here and let the code below set them to proper values. @@ -1195,7 +1181,7 @@ EXTERN_C int usleep(unsigned int); This header file bug is corrected in gcc-2.5.8 and later versions. --Kaveh Ghazi (ghazi@noc.rutgers.edu) 10/3/94. */ -#if defined(uts) || (defined(m88k) && defined(ghs)) +#if defined(m88k) && defined(ghs) # undef S_ISDIR # undef S_ISCHR # undef S_ISBLK @@ -1366,11 +1352,20 @@ EXTERN_C char *crypt(const char *, const char *); #ifdef PERL_CORE # define DEFSV (0 + GvSVn(PL_defgv)) +# define DEFSV_set(sv) \ + (SvREFCNT_dec(GvSV(PL_defgv)), GvSV(PL_defgv) = SvREFCNT_inc(sv)) +# define SAVE_DEFSV \ + ( \ + save_gp(PL_defgv, 0), \ + GvINTRO_off(PL_defgv), \ + SAVEGENERICSV(GvSV(PL_defgv)), \ + GvSV(PL_defgv) = NULL \ + ) #else # define DEFSV GvSVn(PL_defgv) +# define DEFSV_set(sv) (GvSV(PL_defgv) = (sv)) +# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv)) #endif -#define DEFSV_set(sv) (GvSV(PL_defgv) = (sv)) -#define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv)) #define ERRHV GvHV(PL_errgv) /* XXX unused, here for compatibility */ @@ -1383,13 +1378,13 @@ EXTERN_C char *crypt(const char *, const char *); #endif #ifdef HAS_STRERROR +#ifndef DONT_DECLARE_STD # ifdef VMS char *strerror (int,...); # else -#ifndef DONT_DECLARE_STD char *strerror (int); -#endif # endif +#endif # ifndef Strerror # define Strerror strerror # endif @@ -1629,10 +1624,6 @@ EXTERN_C char *crypt(const char *, const char *); #undef UV #endif -#ifdef SPRINTF_E_BUG -# define sprintf UTS_sprintf_wrap -#endif - /* For the times when you want the return value of sprintf, and you want it to be the length. Can't have a thread variable passed in, because C89 has no varargs macros. @@ -1695,13 +1686,6 @@ EXTERN_C char *crypt(const char *, const char *); # define my_strlcpy Perl_my_strlcpy #endif -/* Configure gets this right but the UTS compiler gets it wrong. - -- Hal Morris */ -#ifdef UTS -# undef UVTYPE -# define UVTYPE unsigned -#endif - /* The IV type is supposed to be long enough to hold any integral value or a pointer. @@ -1767,11 +1751,6 @@ typedef UVTYPE UV; # undef PERL_NEED_MY_BETOH64 #endif -#if defined(uts) || defined(UTS) -# undef UV_MAX -# define UV_MAX (4294967295u) -#endif - #define IV_DIG (BIT_DIGITS(IVSIZE * 8)) #define UV_DIG (BIT_DIGITS(UVSIZE * 8)) @@ -2416,14 +2395,18 @@ typedef struct padop PADOP; typedef struct pvop PVOP; typedef struct loop LOOP; +#ifdef PERL_CORE +typedef struct opslab OPSLAB; +typedef struct opslot OPSLOT; +#endif + typedef struct block_hooks BHK; typedef struct custom_op XOP; typedef struct interpreter PerlInterpreter; -/* Amdahl's has struct sv */ /* SGI's has struct sv */ -#if defined(UTS) || defined(__sgi) +#if defined(__sgi) # define STRUCT_SV perl_sv #else # define STRUCT_SV sv @@ -2459,6 +2442,13 @@ typedef struct ptr_tbl_ent PTR_TBL_ENT_t; typedef struct ptr_tbl PTR_TBL_t; typedef struct clone_params CLONE_PARAMS; +/* a pad or name pad is currently just an AV; but that might change, + * so hide the type. */ +typedef struct padlist PADLIST; +typedef AV PAD; +typedef AV PADNAMELIST; +typedef SV PADNAME; + #include "handy.h" #if defined(USE_LARGE_FILES) && !defined(NO_64_BIT_RAWIO) @@ -2581,11 +2571,6 @@ typedef struct clone_params CLONE_PARAMS; #if defined(VMS) # include "vmsish.h" -# include "embed.h" -# ifndef PERL_MAD -# undef op_getmad -# define op_getmad(arg,pegop,slot) NOOP -# endif # define ISHISH "vms" #endif @@ -2615,11 +2600,6 @@ typedef struct clone_params CLONE_PARAMS; #ifdef __SYMBIAN32__ # include "symbian/symbianish.h" -# include "embed.h" -# ifndef PERL_MAD -# undef op_getmad -# define op_getmad(arg,pegop,slot) NOOP -# endif # define ISHISH "symbian" #endif @@ -2733,12 +2713,12 @@ typedef struct clone_params CLONE_PARAMS; #endif /* -=for apidoc Am|void|PERL_SYS_INIT|int argc|char** argv +=for apidoc Am|void|PERL_SYS_INIT|int *argc|char*** argv Provides system-specific tune up of the C runtime environment necessary to run Perl interpreters. This should be called only once, before creating any Perl interpreters. -=for apidoc Am|void|PERL_SYS_INIT3|int argc|char** argv|char** env +=for apidoc Am|void|PERL_SYS_INIT3|int *argc|char*** argv|char*** env Provides system-specific tune up of the C runtime environment necessary to run Perl interpreters. This should be called only once, before creating any Perl interpreters. @@ -2776,11 +2756,7 @@ freeing any remaining Perl interpreters. # define MAXPATHLEN (PATH_MAX+1) # endif # else -# ifdef _POSIX_PATH_MAX -# define MAXPATHLEN _POSIX_PATH_MAX -# else -# define MAXPATHLEN 1024 /* Err on the large side. */ -# endif +# define MAXPATHLEN 1024 /* Err on the large side. */ # endif #endif @@ -3293,9 +3269,9 @@ typedef pthread_key_t perl_key; appropriate to call return. In either case, include the lint directive. */ #ifdef HASATTRIBUTE_NORETURN -# define NORETURN_FUNCTION_END /* NOTREACHED */ +# define NORETURN_FUNCTION_END assert(0); /* NOTREACHED */ #else -# define NORETURN_FUNCTION_END /* NOTREACHED */ return 0 +# define NORETURN_FUNCTION_END assert(0); /* NOTREACHED */ return 0 #endif /* Some OS warn on NULL format to printf */ @@ -3481,7 +3457,9 @@ struct _sublex_info { U16 sub_inwhat; /* "lex_inwhat" to use */ OP *sub_op; /* "lex_op" to use */ char *super_bufptr; /* PL_parser->bufptr that was */ - char *super_bufend; /* PL_parser->bufend that was */ + char *re_eval_start;/* start of "(?{..." text */ + SV *re_eval_str; /* "(?{...})" text */ + SV *repl; /* replacement of s/// or y/// */ }; #include "parser.h" @@ -3506,10 +3484,6 @@ struct ptr_tbl { struct ptr_tbl_ent *tbl_arena_end; }; -#if defined(iAPX286) || defined(M_I286) || defined(I80286) -# define I286 -#endif - #if defined(htonl) && !defined(HAS_HTONL) #define HAS_HTONL #endif @@ -3674,7 +3648,7 @@ Gid_t getegid (void); #define DEBUG_H_FLAG 0x00002000 /* 8192 */ #define DEBUG_X_FLAG 0x00004000 /* 16384 */ #define DEBUG_D_FLAG 0x00008000 /* 32768 */ -/* 0x00010000 is unused, used to be S */ +#define DEBUG_S_FLAG 0x00010000 /* 65536 */ #define DEBUG_T_FLAG 0x00020000 /* 131072 */ #define DEBUG_R_FLAG 0x00040000 /* 262144 */ #define DEBUG_J_FLAG 0x00080000 /* 524288 */ @@ -3684,7 +3658,7 @@ Gid_t getegid (void); #define DEBUG_q_FLAG 0x00800000 /*8388608 */ #define DEBUG_M_FLAG 0x01000000 /*16777216*/ #define DEBUG_B_FLAG 0x02000000 /*33554432*/ -#define DEBUG_MASK 0x03FEEFFF /* mask of all the standard flags */ +#define DEBUG_MASK 0x03FFEFFF /* mask of all the standard flags */ #define DEBUG_DB_RECURSE_FLAG 0x40000000 #define DEBUG_TOP_FLAG 0x80000000 /* XXX what's this for ??? Signal @@ -3706,6 +3680,7 @@ Gid_t getegid (void); # define DEBUG_H_TEST_ (PL_debug & DEBUG_H_FLAG) # define DEBUG_X_TEST_ (PL_debug & DEBUG_X_FLAG) # define DEBUG_D_TEST_ (PL_debug & DEBUG_D_FLAG) +# define DEBUG_S_TEST_ (PL_debug & DEBUG_S_FLAG) # define DEBUG_T_TEST_ (PL_debug & DEBUG_T_FLAG) # define DEBUG_R_TEST_ (PL_debug & DEBUG_R_FLAG) # define DEBUG_J_TEST_ (PL_debug & DEBUG_J_FLAG) @@ -3737,6 +3712,7 @@ Gid_t getegid (void); # define DEBUG_H_TEST DEBUG_H_TEST_ # define DEBUG_X_TEST DEBUG_X_TEST_ # define DEBUG_D_TEST DEBUG_D_TEST_ +# define DEBUG_S_TEST DEBUG_S_TEST_ # define DEBUG_T_TEST DEBUG_T_TEST_ # define DEBUG_R_TEST DEBUG_R_TEST_ # define DEBUG_J_TEST DEBUG_J_TEST_ @@ -3788,6 +3764,7 @@ Gid_t getegid (void); # define DEBUG_Uv(a) DEBUG__(DEBUG_Uv_TEST, a) # define DEBUG_Pv(a) DEBUG__(DEBUG_Pv_TEST, a) +# define DEBUG_S(a) DEBUG__(DEBUG_S_TEST, a) # define DEBUG_T(a) DEBUG__(DEBUG_T_TEST, a) # define DEBUG_R(a) DEBUG__(DEBUG_R_TEST, a) # define DEBUG_v(a) DEBUG__(DEBUG_v_TEST, a) @@ -3815,6 +3792,7 @@ Gid_t getegid (void); # define DEBUG_H_TEST (0) # define DEBUG_X_TEST (0) # define DEBUG_D_TEST (0) +# define DEBUG_S_TEST (0) # define DEBUG_T_TEST (0) # define DEBUG_R_TEST (0) # define DEBUG_J_TEST (0) @@ -3846,6 +3824,7 @@ Gid_t getegid (void); # define DEBUG_H(a) # define DEBUG_X(a) # define DEBUG_D(a) +# define DEBUG_S(a) # define DEBUG_T(a) # define DEBUG_R(a) # define DEBUG_v(a) @@ -3882,6 +3861,11 @@ Gid_t getegid (void); #ifndef assert # define assert(what) Perl_assert(what) #endif +#ifdef DEBUGGING +# define assert_(what) assert(what), +#else +# define assert_(what) +#endif struct ufuncs { I32 (*uf_val)(pTHX_ IV, SV*); @@ -4611,7 +4595,9 @@ EXTCONST unsigned char PL_freq[] = { /* letter frequencies for mixed English/C * EXTCONST unsigned char PL_freq[]; #endif -#ifdef DEBUGGING +/* Although only used for debugging, these constants must be available in + * non-debugging builds too, since they're used in ext/re/re_exec.c, + * which has DEBUGGING enabled always */ #ifdef DOINIT EXTCONST char* const PL_block_type[] = { "NULL", @@ -4630,7 +4616,6 @@ EXTCONST char* const PL_block_type[] = { #else EXTCONST char* PL_block_type[]; #endif -#endif /* These are all the compile time options that affect binary compatibility. Other compile time options that are binary compatible are in perl.c @@ -4702,12 +4687,6 @@ EXTCONST char PL_bincompat_options[] = # ifdef PERL_USES_PL_PIDSTATUS " PERL_USES_PL_PIDSTATUS" # endif -# ifdef PL_OP_SLAB_ALLOC - " PL_OP_SLAB_ALLOC" -# endif -# ifdef THREADS_HAVE_PIDS - " THREADS_HAVE_PIDS" -# endif # ifdef USE_64_BIT_ALL " USE_64_BIT_ALL" # endif @@ -4795,6 +4774,8 @@ EXTCONST char *const PL_phase_names[]; * instead of using the newer PL_phase, which provides everything PL_dirty * provided, and more. */ # define PL_dirty (PL_phase == PERL_PHASE_DESTRUCT) + +# define PL_amagic_generation PL_na #endif /* !PERL_CORE */ END_EXTERN_C @@ -4836,8 +4817,11 @@ typedef enum { #define HINT_STRICT_REFS 0x00000002 /* strict pragma */ #define HINT_LOCALE 0x00000004 /* locale pragma */ #define HINT_BYTES 0x00000008 /* bytes pragma */ - /* Note: 20,40,80 used for NATIVE_HINTS */ - /* currently defined by vms/vmsish.h */ +#define HINT_LOCALE_NOT_CHARS 0x00000010 /* locale ':not_characters' pragma */ + +#define HINT_EXPLICIT_STRICT_REFS 0x00000020 /* strict.pm */ +#define HINT_EXPLICIT_STRICT_SUBS 0x00000040 /* strict.pm */ +#define HINT_EXPLICIT_STRICT_VARS 0x00000080 /* strict.pm */ #define HINT_BLOCK_SCOPE 0x00000100 #define HINT_STRICT_SUBS 0x00000200 /* strict pragma */ @@ -4864,6 +4848,14 @@ typedef enum { #define HINT_RE_FLAGS 0x02000000 /* re '/xism' pragma */ +#define HINT_FEATURE_MASK 0x1c000000 /* 3 bits for feature bundles */ + + /* Note: Used for NATIVE_HINTS, currently + defined by vms/vmsish.h: + 0x40000000 + 0x80000000 + */ + /* The following are stored in $^H{sort}, not in PL_hints */ #define HINT_SORT_SORT_BITS 0x000000FF /* allow 256 different ones */ #define HINT_SORT_QUICKSORT 0x00000001 @@ -5026,6 +5018,10 @@ struct tempsym; /* defined in pp_pack.c */ # define PERL_CALLCONV # endif #endif +#ifndef PERL_CALLCONV_NO_RET +# define PERL_CALLCONV_NO_RET PERL_CALLCONV +#endif + #undef PERL_CKDEF #undef PERL_PPDEF #define PERL_CKDEF(s) PERL_CALLCONV OP *s (pTHX_ OP *o); @@ -5073,13 +5069,13 @@ END_EXTERN_C # undef PL_na #endif -#if defined(WIN32) -/* Now all the config stuff is setup we can include embed.h */ -# include "embed.h" -# ifndef PERL_MAD -# undef op_getmad -# define op_getmad(arg,pegop,slot) NOOP -# endif +/* Now all the config stuff is setup we can include embed.h + In particular, need the relevant *ish file included already, as it may + define HAVE_INTERP_INTERN */ +#include "embed.h" +#ifndef PERL_MAD +# undef op_getmad +# define op_getmad(arg,pegop,slot) NOOP #endif #ifndef PERL_GLOBAL_STRUCT @@ -5162,6 +5158,8 @@ EXTCONST bool PL_valid_types_NV_set[]; #endif +/* Static inline funcs that depend on includes and declarations above */ +#include "inline.h" #include "overload.h" @@ -5172,7 +5170,6 @@ struct am_table { U8 fallback; U16 spare; U32 was_ok_sub; - long was_ok_am; CV* table[NofAMmeth]; }; struct am_table_short { @@ -5180,7 +5177,6 @@ struct am_table_short { U8 fallback; U16 spare; U32 was_ok_sub; - long was_ok_am; }; typedef struct am_table AMT; typedef struct am_table_short AMTS; @@ -5274,11 +5270,23 @@ typedef struct am_table_short AMTS; #define SET_NUMERIC_LOCAL() \ set_numeric_local(); +/* Returns non-zero If the plain locale pragma without a parameter is in effect + */ #define IN_LOCALE_RUNTIME (CopHINTS_get(PL_curcop) & HINT_LOCALE) + +/* Returns non-zero If either form of the locale pragma is in effect */ +#define IN_SOME_LOCALE_FORM_RUNTIME \ + (CopHINTS_get(PL_curcop) & (HINT_LOCALE|HINT_LOCALE_NOT_CHARS)) + #define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE) +#define IN_SOME_LOCALE_FORM_COMPILETIME \ + (PL_hints & (HINT_LOCALE|HINT_LOCALE_NOT_CHARS)) #define IN_LOCALE \ (IN_PERL_COMPILETIME ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME) +#define IN_SOME_LOCALE_FORM \ + (IN_PERL_COMPILETIME ? IN_SOME_LOCALE_FORM_COMPILETIME \ + : IN_SOME_LOCALE_FORM_RUNTIME) #define STORE_NUMERIC_LOCAL_SET_STANDARD() \ bool was_local = PL_numeric_local && IN_LOCALE; \ @@ -5307,10 +5315,12 @@ typedef struct am_table_short AMTS; #define RESTORE_NUMERIC_STANDARD() /**/ #define Atof my_atof #define IN_LOCALE_RUNTIME 0 +#define IN_LOCALE_COMPILETIME 0 #endif /* !USE_LOCALE_NUMERIC */ -#if !defined(Strtol) && defined(USE_64_BIT_INT) && defined(IV_IS_QUAD) && QUADKIND == QUAD_IS_LONG_LONG +#if !defined(Strtol) && defined(USE_64_BIT_INT) && defined(IV_IS_QUAD) && \ + (QUADKIND == QUAD_IS_LONG_LONG || QUADKIND == QUAD_IS___INT64) # ifdef __hpux # define strtoll __strtoll /* secret handshake */ # endif @@ -5332,7 +5342,8 @@ typedef struct am_table_short AMTS; /* It would be more fashionable to use Strtol() to define atol() * (as is done for Atoul(), see below) but for backward compatibility * we just assume atol(). */ -# if defined(USE_64_BIT_INT) && defined(IV_IS_QUAD) && QUADKIND == QUAD_IS_LONG_LONG && defined(HAS_ATOLL) +# if defined(USE_64_BIT_INT) && defined(IV_IS_QUAD) && defined(HAS_ATOLL) && \ + (QUADKIND == QUAD_IS_LONG_LONG || QUADKIND == QUAD_IS___INT64) # ifdef WIN64 # define atoll _atoi64 /* secret handshake */ # endif @@ -5342,7 +5353,8 @@ typedef struct am_table_short AMTS; # endif #endif -#if !defined(Strtoul) && defined(USE_64_BIT_INT) && defined(UV_IS_QUAD) && QUADKIND == QUAD_IS_LONG_LONG +#if !defined(Strtoul) && defined(USE_64_BIT_INT) && defined(UV_IS_QUAD) && \ + (QUADKIND == QUAD_IS_LONG_LONG || QUADKIND == QUAD_IS___INT64) # ifdef __hpux # define strtoull __strtoull /* secret handshake */ # endif @@ -5498,10 +5510,12 @@ typedef struct am_table_short AMTS; * the interpreter goes away.) */ # define MY_CXT_INIT \ my_cxt_t *my_cxtp = \ - (my_cxt_t*)Perl_my_cxt_init(aTHX_ MY_CXT_INIT_ARG, sizeof(my_cxt_t)) + (my_cxt_t*)Perl_my_cxt_init(aTHX_ MY_CXT_INIT_ARG, sizeof(my_cxt_t)); \ + PERL_UNUSED_VAR(my_cxtp) # define MY_CXT_INIT_INTERP(my_perl) \ my_cxt_t *my_cxtp = \ - (my_cxt_t*)Perl_my_cxt_init(my_perl, MY_CXT_INIT_ARG, sizeof(my_cxt_t)) + (my_cxt_t*)Perl_my_cxt_init(my_perl, MY_CXT_INIT_ARG, sizeof(my_cxt_t)); \ + PERL_UNUSED_VAR(my_cxtp) /* This declaration should be used within all functions that use the * interpreter-local data. */ @@ -5518,7 +5532,7 @@ typedef struct am_table_short AMTS; /* This macro must be used to access members of the my_cxt_t structure. - * e.g. MYCXT.some_data */ + * e.g. MY_CXT.some_data */ # define MY_CXT (*my_cxtp) /* Judicious use of these macros can reduce the number of times dMY_CXT @@ -5766,14 +5780,6 @@ extern void moncontrol(int); #define PERL_PV_PRETTY_DUMP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_QUOTE #define PERL_PV_PRETTY_REGPROP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_LTGT|PERL_PV_ESCAPE_RE|PERL_PV_ESCAPE_NONASCII -#ifdef PERL_CORE -# define FEATURE_IS_ENABLED(name) \ - ((0 != (PL_hints & HINT_LOCALIZE_HH)) \ - && Perl_feature_is_enabled(aTHX_ STR_WITH_LEN(name))) -/* The longest string we pass in. */ -# define MAX_FEATURE_LEN (sizeof("unicode_strings")-1) -#endif - /* (KEEP THIS LAST IN perl.h!) @@ -5830,8 +5836,8 @@ extern void moncontrol(int); * Local variables: * c-indentation-style: bsd * c-basic-offset: 4 - * indent-tabs-mode: t + * indent-tabs-mode: nil * End: * - * ex: set ts=8 sts=4 sw=4 noet: + * ex: set ts=8 sts=4 sw=4 et: */