3 require 5.003; # keep this compatible, an old perl is all we may have before
7 # Get function prototypes
8 require 'regen_lib.pl';
12 # See database of global and static function prototypes in embed.fnc
13 # This is used to generate prototype headers under various configurations,
14 # export symbols lists for different platforms, and macros to provide an
15 # implicit interpreter context argument.
22 my $years = '1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005';
24 $years =~ s/1999,/1999,\n / if length $years > 40;
27 -*- buffer-read-only: t -*-
31 Copyright (C) $years, by Larry Wall and others
33 You may distribute under the terms of either the GNU General Public
34 License or the Artistic License, as specified in the README file.
36 !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
37 This file is built by embed.pl from data in embed.fnc, embed.pl,
38 pp.sym, intrpvar.h, perlvars.h and thrdvar.h.
39 Any changes made here will be lost!
41 Edit those files and run 'make regen_headers' to effect changes.
45 $warning .= <<EOW if $file eq 'perlapi.c';
47 Up to the threshold of the door there mounted a flight of twenty-seven
48 broad stairs, hewn by some unknown art of the same black stone. This
49 was the only entrance to the tower.
54 if ($file =~ m:\.[ch]$:) {
55 $warning =~ s:^: * :gm;
56 $warning =~ s: +$::gm;
61 $warning =~ s:^:# :gm;
62 $warning =~ s: +$::gm;
67 open IN, "embed.fnc" or die $!;
69 # walk table providing an array of components in each line to
70 # subroutine, printing the result
73 my $filename = shift || '-';
75 defined $leader or $leader = do_not_edit ($filename);
79 if (ref $filename) { # filehandle
83 safer_unlink $filename if $filename ne '/dev/null';
84 open F, ">$filename" or die "Can't open $filename: $!";
88 print $F $leader if $leader;
89 seek IN, 0, 0; # so we may restart
103 @args = split /\s*\|\s*/, $_;
105 my @outs = &{$function}(@args);
106 print $F @outs; # $function->(@args) is not 5.003
108 print $F $trailer if $trailer;
109 unless (ref $filename) {
110 close $F or die "Error closing $filename: $!";
114 sub munge_c_files () {
117 warn "\@ARGV empty, nothing to do\n";
122 $functions->{$_[2]} = \@_ if $_[@_-1] =~ /\.\.\./;
124 } '/dev/null', '', '';
127 # if (/^#\s*include\s+"perl.h"/) {
128 # my $file = uc $ARGV;
130 # print "#define PERL_IN_$file\n";
136 # if (exists $functions->{$f}) {
137 # my $flags = $functions->{$f}[0];
138 # $repl = "Perl_$repl" if $flags =~ /p/;
139 # unless ($flags =~ /n/) {
141 # $repl .= "_ " if @{$functions->{$f}} > 3;
143 # warn("$ARGV:$.:$repl\n");
147 s{(\b(\w+)[ \t]*\([ \t]*(?!aTHX))}
151 if (exists $functions->{$f}) {
153 warn("$ARGV:$.:$`#$repl#$'");
158 close ARGV if eof; # restart $.
166 my $wrote_protected = 0;
175 my ($flags,$retval,$func,@args) = @_;
177 my $has_context = ( $flags !~ /n/ );
178 $ret .= '/* ' if $flags =~ /m/;
180 $retval = "STATIC $retval";
184 $retval = "PERL_CALLCONV $retval";
186 $func = "Perl_$func";
189 $ret .= "$retval\t$func(";
190 if ( $has_context ) {
191 $ret .= @args ? "pTHX_ " : "pTHX";
195 for my $arg ( @args ) {
197 if ( $arg =~ /\*/ && $arg !~ /\b(NN|NULLOK)\b/ ) {
198 warn "$func: $arg needs NN or NULLOK\n";
199 our $unflagged_pointers;
200 ++$unflagged_pointers;
202 push( @nonnull, $n ) if ( $arg =~ s/\s*\bNN\b\s+// );
203 $arg =~ s/\s*\bNULLOK\b\s+//; # strip NULLOK with no effect
205 $ret .= join ", ", @args;
208 $ret .= "void" if !$has_context;
212 if ( $flags =~ /r/ ) {
213 push @attrs, "__attribute__noreturn__";
215 if ( $flags =~ /a/ ) {
216 push @attrs, "__attribute__malloc__";
217 $flags .= "R"; # All allocing must check return value
219 if ( $flags =~ /R/ ) {
220 push @attrs, "__attribute__warn_unused_result__";
222 if ( $flags =~ /P/ ) {
223 push @attrs, "__attribute__pure__";
225 if( $flags =~ /f/ ) {
226 my $prefix = $has_context ? 'pTHX_' : '';
227 my $args = scalar @args;
228 push @attrs, sprintf "__attribute__format__(__printf__,%s%d,%s%d)",
229 $prefix, $args - 1, $prefix, $args;
232 my @pos = map { $has_context ? "pTHX_$_" : $_ } @nonnull;
233 push @attrs, map { sprintf( "__attribute__nonnull__(%s)", $_ ) } @pos;
237 $ret .= join( "\n", map { "\t\t\t$_" } @attrs );
240 $ret .= ' */' if $flags =~ /m/;
241 $ret .= @attrs ? "\n\n" : "\n";
246 # generates global.sym (API export list)
249 sub write_global_sym {
252 my ($flags,$retval,$func,@args) = @_;
253 # If a function is defined twice, for example before and after an
254 # #else, only process the flags on the first instance for global.sym
255 return $ret if $seen{$func}++;
256 if ($flags =~ /[AX]/ && $flags !~ /[xm]/
257 || $flags =~ /b/) { # public API, so export
258 $func = "Perl_$func" if $flags =~ /[pbX]/;
267 our $unflagged_pointers;
268 walk_table(\&write_protos, "proto.h", undef, "/* ex: set ro: */\n");
269 warn "$unflagged_pointers pointer arguments to clean up\n" if $unflagged_pointers;
270 walk_table(\&write_global_sym, "global.sym", undef, "# ex: set ro:\n");
272 # XXX others that may need adding
276 my @extvars = qw(sv_undef sv_yes sv_no na dowarn
278 tainting tainted stack_base stack_sp sv_arenaroot
280 curstash DBsub DBsingle DBassertion debstash
294 my ($syms, $file) = @_;
296 open(FILE, "< $file")
297 or die "embed.pl: Can't open $file: $!\n";
299 s/[ \t]*#.*//; # Delete comments.
300 if (/^\s*(\S+)\s*$/) {
302 warn "duplicate symbol $sym while processing $file\n"
303 if exists $$syms{$sym};
310 # Perl_pp_* and Perl_ck_* are in pp.sym
311 readsyms my %ppsym, 'pp.sym';
313 sub readvars(\%$$@) {
314 my ($syms, $file,$pre,$keep_pre) = @_;
316 open(FILE, "< $file")
317 or die "embed.pl: Can't open $file: $!\n";
319 s/[ \t]*#.*//; # Delete comments.
320 if (/PERLVARA?I?S?C?\($pre(\w+)/) {
322 $sym = $pre . $sym if $keep_pre;
323 warn "duplicate symbol $sym while processing $file\n"
324 if exists $$syms{$sym};
325 $$syms{$sym} = $pre || 1;
334 readvars %intrp, 'intrpvar.h','I';
335 readvars %thread, 'thrdvar.h','T';
336 readvars %globvar, 'perlvars.h','G';
339 foreach $sym (sort keys %thread) {
340 warn "$sym in intrpvar.h as well as thrdvar.h\n" if exists $intrp{$sym};
349 my ($from, $to) = @_;
350 my $t = int(length($from) / 8);
351 "#define $from" . "\t" x ($t < 3 ? 3 - $t : 1) . "$to\n";
354 sub bincompat_var ($$) {
355 my ($pfx, $sym) = @_;
356 my $arg = ($pfx eq 'G' ? 'NULL' : 'aTHX');
357 undefine("PL_$sym") . hide("PL_$sym", "(*Perl_${pfx}${sym}_ptr($arg))");
361 my ($sym,$pre,$ptr) = @_;
362 hide("PL_$sym", "($ptr$pre$sym)");
367 return hide("PL_$pre$sym", "PL_$sym");
370 safer_unlink 'embed.h';
371 open(EM, '> embed.h') or die "Can't create embed.h: $!\n";
374 print EM do_not_edit ("embed.h"), <<'END';
376 /* (Doing namespace management portably in C is really gross.) */
378 /* By defining PERL_NO_SHORT_NAMES (not done by default) the short forms
379 * (like warn instead of Perl_warn) for the API are not defined.
380 * Not defining the short forms is a good thing for cleaner embedding. */
382 #ifndef PERL_NO_SHORT_NAMES
384 /* Hide global symbols */
386 #if !defined(PERL_IMPLICIT_CONTEXT)
390 # Try to elimiate lots of repeated
397 # by tracking state and merging foo and bar into one block.
398 my $ifdef_state = '';
402 my $new_ifdef_state = '';
405 $ret .= "$arg\n" if $arg =~ /^#\s*(if|ifn?def|else|endif)\b/;
408 my ($flags,$retval,$func,@args) = @_;
409 unless ($flags =~ /[om]/) {
411 $ret .= hide($func,"S_$func");
413 elsif ($flags =~ /p/) {
414 $ret .= hide($func,"Perl_$func");
417 if ($ret ne '' && $flags !~ /A/) {
420 = "#if defined(PERL_CORE) || defined(PERL_EXT)\n";
423 $new_ifdef_state = "#ifdef PERL_CORE\n";
426 if ($new_ifdef_state ne $ifdef_state) {
427 $ret = $new_ifdef_state . $ret;
431 if ($ifdef_state && $new_ifdef_state ne $ifdef_state) {
432 # Close the old one ahead of opening the new one.
433 $ret = "#endif\n$ret";
435 # Remember the new state.
436 $ifdef_state = $new_ifdef_state;
444 for $sym (sort keys %ppsym) {
446 print EM hide($sym, "Perl_$sym");
451 #else /* PERL_IMPLICIT_CONTEXT */
460 my $new_ifdef_state = '';
463 $ret .= "$arg\n" if $arg =~ /^#\s*(if|ifn?def|else|endif)\b/;
466 my ($flags,$retval,$func,@args) = @_;
467 unless ($flags =~ /[om]/) {
468 my $args = scalar @args;
469 if ($args and $args[$args-1] =~ /\.\.\./) {
470 # we're out of luck for varargs functions under CPP
472 elsif ($flags =~ /n/) {
474 $ret .= hide($func,"S_$func");
476 elsif ($flags =~ /p/) {
477 $ret .= hide($func,"Perl_$func");
481 my $alist = join(",", @az[0..$args-1]);
482 $ret = "#define $func($alist)";
483 my $t = int(length($ret) / 8);
484 $ret .= "\t" x ($t < 4 ? 4 - $t : 1);
486 $ret .= "S_$func(aTHX";
488 elsif ($flags =~ /p/) {
489 $ret .= "Perl_$func(aTHX";
491 $ret .= "_ " if $alist;
492 $ret .= $alist . ")\n";
495 unless ($flags =~ /A/) {
498 = "#if defined(PERL_CORE) || defined(PERL_EXT)\n";
501 $new_ifdef_state = "#ifdef PERL_CORE\n";
504 if ($new_ifdef_state ne $ifdef_state) {
505 $ret = $new_ifdef_state . $ret;
509 if ($ifdef_state && $new_ifdef_state ne $ifdef_state) {
510 # Close the old one ahead of opening the new one.
511 $ret = "#endif\n$ret";
513 # Remember the new state.
514 $ifdef_state = $new_ifdef_state;
522 for $sym (sort keys %ppsym) {
524 if ($sym =~ /^ck_/) {
525 print EM hide("$sym(a)", "Perl_$sym(aTHX_ a)");
527 elsif ($sym =~ /^pp_/) {
528 print EM hide("$sym()", "Perl_$sym(aTHX)");
531 warn "Illegal symbol '$sym' in pp.sym";
537 #endif /* PERL_IMPLICIT_CONTEXT */
539 #endif /* #ifndef PERL_NO_SHORT_NAMES */
545 /* Compatibility stubs. Compile extensions with -DPERL_NOCOMPAT to
549 #if !defined(PERL_CORE)
550 # define sv_setptrobj(rv,ptr,name) sv_setref_iv(rv,name,PTR2IV(ptr))
551 # define sv_setptrref(rv,ptr) sv_setref_iv(rv,Nullch,PTR2IV(ptr))
554 #if !defined(PERL_CORE) && !defined(PERL_NOCOMPAT)
556 /* Compatibility for various misnamed functions. All functions
557 in the API that begin with "perl_" (not "Perl_") take an explicit
558 interpreter context pointer.
559 The following are not like that, but since they had a "perl_"
560 prefix in previous versions, we provide compatibility macros.
562 # define perl_atexit(a,b) call_atexit(a,b)
563 # define perl_call_argv(a,b,c) call_argv(a,b,c)
564 # define perl_call_pv(a,b) call_pv(a,b)
565 # define perl_call_method(a,b) call_method(a,b)
566 # define perl_call_sv(a,b) call_sv(a,b)
567 # define perl_eval_sv(a,b) eval_sv(a,b)
568 # define perl_eval_pv(a,b) eval_pv(a,b)
569 # define perl_require_pv(a) require_pv(a)
570 # define perl_get_sv(a,b) get_sv(a,b)
571 # define perl_get_av(a,b) get_av(a,b)
572 # define perl_get_hv(a,b) get_hv(a,b)
573 # define perl_get_cv(a,b) get_cv(a,b)
574 # define perl_init_i18nl10n(a) init_i18nl10n(a)
575 # define perl_init_i18nl14n(a) init_i18nl14n(a)
576 # define perl_new_ctype(a) new_ctype(a)
577 # define perl_new_collate(a) new_collate(a)
578 # define perl_new_numeric(a) new_numeric(a)
580 /* varargs functions can't be handled with CPP macros. :-(
581 This provides a set of compatibility functions that don't take
582 an extra argument but grab the context pointer using the macro
585 #if defined(PERL_IMPLICIT_CONTEXT) && !defined(PERL_NO_SHORT_NAMES)
586 # define croak Perl_croak_nocontext
587 # define deb Perl_deb_nocontext
588 # define die Perl_die_nocontext
589 # define form Perl_form_nocontext
590 # define load_module Perl_load_module_nocontext
591 # define mess Perl_mess_nocontext
592 # define newSVpvf Perl_newSVpvf_nocontext
593 # define sv_catpvf Perl_sv_catpvf_nocontext
594 # define sv_setpvf Perl_sv_setpvf_nocontext
595 # define warn Perl_warn_nocontext
596 # define warner Perl_warner_nocontext
597 # define sv_catpvf_mg Perl_sv_catpvf_mg_nocontext
598 # define sv_setpvf_mg Perl_sv_setpvf_mg_nocontext
601 #endif /* !defined(PERL_CORE) && !defined(PERL_NOCOMPAT) */
603 #if !defined(PERL_IMPLICIT_CONTEXT)
604 /* undefined symbols, point them back at the usual ones */
605 # define Perl_croak_nocontext Perl_croak
606 # define Perl_die_nocontext Perl_die
607 # define Perl_deb_nocontext Perl_deb
608 # define Perl_form_nocontext Perl_form
609 # define Perl_load_module_nocontext Perl_load_module
610 # define Perl_mess_nocontext Perl_mess
611 # define Perl_newSVpvf_nocontext Perl_newSVpvf
612 # define Perl_sv_catpvf_nocontext Perl_sv_catpvf
613 # define Perl_sv_setpvf_nocontext Perl_sv_setpvf
614 # define Perl_warn_nocontext Perl_warn
615 # define Perl_warner_nocontext Perl_warner
616 # define Perl_sv_catpvf_mg_nocontext Perl_sv_catpvf_mg
617 # define Perl_sv_setpvf_mg_nocontext Perl_sv_setpvf_mg
623 close(EM) or die "Error closing EM: $!";
625 safer_unlink 'embedvar.h';
626 open(EM, '> embedvar.h')
627 or die "Can't create embedvar.h: $!\n";
630 print EM do_not_edit ("embedvar.h"), <<'END';
632 /* (Doing namespace management portably in C is really gross.) */
635 The following combinations of MULTIPLICITY and PERL_IMPLICIT_CONTEXT
638 2) MULTIPLICITY # supported for compatibility
639 3) MULTIPLICITY && PERL_IMPLICIT_CONTEXT
641 All other combinations of these flags are errors.
643 only #3 is supported directly, while #2 is a special
644 case of #3 (supported by redefining vTHX appropriately).
647 #if defined(MULTIPLICITY)
648 /* cases 2 and 3 above */
650 # if defined(PERL_IMPLICIT_CONTEXT)
653 # define vTHX PERL_GET_INTERP
658 for $sym (sort keys %thread) {
659 print EM multon($sym,'T','vTHX->');
664 /* cases 2 and 3 above */
668 for $sym (sort keys %intrp) {
669 print EM multon($sym,'I','vTHX->');
674 #else /* !MULTIPLICITY */
680 for $sym (sort keys %intrp) {
681 print EM multoff($sym,'I');
688 for $sym (sort keys %thread) {
689 print EM multoff($sym,'T');
694 #endif /* MULTIPLICITY */
696 #if defined(PERL_GLOBAL_STRUCT)
700 for $sym (sort keys %globvar) {
701 print EM multon($sym, 'G','my_vars->');
702 print EM multon("G$sym",'', 'my_vars->');
707 #else /* !PERL_GLOBAL_STRUCT */
711 for $sym (sort keys %globvar) {
712 print EM multoff($sym,'G');
717 #endif /* PERL_GLOBAL_STRUCT */
719 #ifdef PERL_POLLUTE /* disabled by default in 5.6.0 */
723 for $sym (sort @extvars) {
724 print EM hide($sym,"PL_$sym");
729 #endif /* PERL_POLLUTE */
734 close(EM) or die "Error closing EM: $!";
736 safer_unlink 'perlapi.h';
737 safer_unlink 'perlapi.c';
738 open(CAPI, '> perlapi.c') or die "Can't create perlapi.c: $!\n";
740 open(CAPIH, '> perlapi.h') or die "Can't create perlapi.h: $!\n";
743 print CAPIH do_not_edit ("perlapi.h"), <<'EOT';
745 /* declare accessor functions for Perl variables */
746 #ifndef __perlapi_h__
747 #define __perlapi_h__
749 #if defined (MULTIPLICITY)
758 #define PERLVAR(v,t) EXTERN_C t* Perl_##v##_ptr(pTHX);
759 #define PERLVARA(v,n,t) typedef t PL_##v##_t[n]; \
760 EXTERN_C PL_##v##_t* Perl_##v##_ptr(pTHX);
761 #define PERLVARI(v,t,i) PERLVAR(v,t)
762 #define PERLVARIC(v,t,i) PERLVAR(v, const t)
763 #define PERLVARISC(v,i) typedef const char PL_##v##_t[sizeof(i)]; \
764 EXTERN_C PL_##v##_t* Perl_##v##_ptr(pTHX);
767 #include "intrpvar.h"
768 #include "perlvars.h"
776 #ifndef PERL_GLOBAL_STRUCT
777 EXTERN_C Perl_ppaddr_t** Perl_Gppaddr_ptr(pTHX);
778 EXTERN_C Perl_check_t** Perl_Gcheck_ptr(pTHX);
779 EXTERN_C unsigned char** Perl_Gfold_locale_ptr(pTHX);
780 #define Perl_ppaddr_ptr Perl_Gppaddr_ptr
781 #define Perl_check_ptr Perl_Gcheck_ptr
782 #define Perl_fold_locale_ptr Perl_Gfold_locale_ptr
787 #if defined(PERL_CORE)
789 /* accessor functions for Perl variables (provide binary compatibility) */
791 /* these need to be mentioned here, or most linkers won't put them in
792 the perl executable */
794 #ifndef PERL_NO_FORCE_LINK
799 EXTCONST void * const PL_force_link_funcs[];
801 EXTCONST void * const PL_force_link_funcs[] = {
806 #define PERLVAR(v,t) (void*)Perl_##v##_ptr,
807 #define PERLVARA(v,n,t) PERLVAR(v,t)
808 #define PERLVARI(v,t,i) PERLVAR(v,t)
809 #define PERLVARIC(v,t,i) PERLVAR(v,t)
810 #define PERLVARISC(v,i) PERLVAR(v,char)
812 /* In Tru64 (__DEC && __osf__) the cc option -std1 causes that one
813 * cannot cast between void pointers and function pointers without
814 * info level warnings. The PL_force_link_funcs[] would cause a few
815 * hundred of those warnings. In code one can circumnavigate this by using
816 * unions that overlay the different pointers, but in declarations one
817 * cannot use this trick. Therefore we just disable the warning here
818 * for the duration of the PL_force_link_funcs[] declaration. */
820 #if defined(__DECC) && defined(__osf__)
822 #pragma message disable (nonstandcast)
826 #include "intrpvar.h"
827 #include "perlvars.h"
829 #if defined(__DECC) && defined(__osf__)
830 #pragma message restore
843 #endif /* PERL_NO_FORCE_LINK */
845 #else /* !PERL_CORE */
849 foreach $sym (sort keys %intrp) {
850 print CAPIH bincompat_var('I',$sym);
853 foreach $sym (sort keys %thread) {
854 print CAPIH bincompat_var('T',$sym);
857 foreach $sym (sort keys %globvar) {
858 print CAPIH bincompat_var('G',$sym);
863 #endif /* !PERL_CORE */
864 #endif /* MULTIPLICITY */
866 #endif /* __perlapi_h__ */
870 close CAPIH or die "Error closing CAPIH: $!";
872 print CAPI do_not_edit ("perlapi.c"), <<'EOT';
878 #if defined (MULTIPLICITY)
880 /* accessor functions for Perl variables (provides binary compatibility) */
889 #define PERLVAR(v,t) t* Perl_##v##_ptr(pTHX) \
890 { dVAR; return &(aTHX->v); }
891 #define PERLVARA(v,n,t) PL_##v##_t* Perl_##v##_ptr(pTHX) \
892 { dVAR; return &(aTHX->v); }
894 #define PERLVARI(v,t,i) PERLVAR(v,t)
895 #define PERLVARIC(v,t,i) PERLVAR(v, const t)
896 #define PERLVARISC(v,i) PL_##v##_t* Perl_##v##_ptr(pTHX) \
897 { dVAR; return &(aTHX->v); }
900 #include "intrpvar.h"
904 #define PERLVAR(v,t) t* Perl_##v##_ptr(pTHX) \
905 { dVAR; return &(PL_##v); }
906 #define PERLVARA(v,n,t) PL_##v##_t* Perl_##v##_ptr(pTHX) \
907 { dVAR; return &(PL_##v); }
910 #define PERLVARIC(v,t,i) \
911 const t* Perl_##v##_ptr(pTHX) \
912 { return (const t *)&(PL_##v); }
913 #define PERLVARISC(v,i) PL_##v##_t* Perl_##v##_ptr(pTHX) \
914 { dVAR; return &(PL_##v); }
915 #include "perlvars.h"
923 #ifndef PERL_GLOBAL_STRUCT
924 /* A few evil special cases. Could probably macrofy this. */
927 #undef PL_fold_locale
928 Perl_ppaddr_t** Perl_Gppaddr_ptr(pTHX) {
929 static const Perl_ppaddr_t* ppaddr_ptr = PL_ppaddr;
930 return (Perl_ppaddr_t**)&ppaddr_ptr;
932 Perl_check_t** Perl_Gcheck_ptr(pTHX) {
933 static const Perl_check_t* check_ptr = PL_check;
934 return (Perl_check_t**)&check_ptr;
936 unsigned char** Perl_Gfold_locale_ptr(pTHX) {
937 static const unsigned char* fold_locale_ptr = PL_fold_locale;
938 return (unsigned char**)&fold_locale_ptr;
944 #endif /* MULTIPLICITY */
949 close(CAPI) or die "Error closing CAPI: $!";
951 # functions that take va_list* for implementing vararg functions
952 # NOTE: makedef.pl must be updated if you add symbols to %vfuncs
953 # XXX %vfuncs currently unused
955 Perl_croak Perl_vcroak
957 Perl_warner Perl_vwarner
960 Perl_load_module Perl_vload_module
963 Perl_newSVpvf Perl_vnewSVpvf
964 Perl_sv_setpvf Perl_sv_vsetpvf
965 Perl_sv_setpvf_mg Perl_sv_vsetpvf_mg
966 Perl_sv_catpvf Perl_sv_vcatpvf
967 Perl_sv_catpvf_mg Perl_sv_vcatpvf_mg
968 Perl_dump_indent Perl_dump_vindent
969 Perl_default_protect Perl_vdefault_protect
972 # ex: set ts=8 sts=4 sw=4 noet: