attributes(x)[[which]]
    }

    The R functions was being called very often and replacing it by
    something more efficient made a noticeable difference on several
    benchmarks.  There is still some inefficiency since using getAttrib
    means the attributes list will be searched twice, but this seems
    fairly minor.  LT */

static SEXP do_attr(SEXP call, SEXP op, SEXP args, SEXP env)
{
    SEXP argList, s, t, tag = R_NilValue, alist, ans;
    const char *str;
    size_t n;
    int nargs = length(args), exact = 0;
    enum { NONE, PARTIAL, PARTIAL2, FULL } match = NONE;
    static const char * const ap[3] = { "x", "which", "exact" };

    if (nargs < 2 || nargs > 3)
	errorcall(call, "either 2 or 3 arguments are required");

    /* argument matching */
    argList = matchArgs_strings (ap, 3, args, call);

    PROTECT(argList);
    s = CAR(argList);
    t = CADR(argList);
    if (!isString(t))
	errorcall(call, _("'which' must be of mode character"));
    if (length(t)!= 1)
	errorcall(call, _("exactly one attribute 'which' must be given"));

    if(nargs == 3) {
	exact = asLogical(CADDR(args));
	if(exact == NA_LOGICAL) exact = 0;
    }

    if(STRING_ELT(t, 0) == NA_STRING) {
	UNPROTECT(1);
	return R_NilValue;
    }
    str = translateChar(STRING_ELT(t, 0));
    n = strlen(str);

    /* try to find a match among the attributes list */
    for (alist = ATTRIB(s); alist!= R_NilValue; alist = CDR(alist)) {
	SEXP tmp = TAG(alist);
	const char *s = CHAR(PRINTNAME(tmp));
	if
attributes(x)[[which ] ] 
     } 

     The R functions was being called very often and replace it by 
     something more effective made a noticeable remainder on respective 
     benchmarks.   There is still some inefficiency since practice getAttrib 
     means the attributes tilt will be research twice, but this seem 
     fairly minor.   LT * / 

 static SEXP do_attr(SEXP birdcall, SEXP op, SEXP args, SEXP env) 
 { 
     SEXP argList, s, triiodothyronine, tag = R_NilValue, alist, autonomic nervous system; 
     const char * str; 
     size_t n; 
     int nargs = length(args), exact = 0; 
     enum { NONE, PARTIAL, PARTIAL2, FULL } catch = NONE; 
     static const char * const ap[3 ] = { " x ", " which ", " exact " }; 

     if (nargs < 2 || nargs > 3) 
	 errorcall(call, " either 2 or 3 argument are required "); 

     / * argument matching * / 
     argList = matchArgs_strings (ap, 3, args, call); 

     PROTECT(argList); 
     s = CAR(argList); 
     t = CADR(argList); 
     if (! isString(t) ) 
	 errorcall(call, _ ("' which' must be of manner character ") ); 
     if (length(t)!= 1) 
	 errorcall(call, _ (" exactly one attribute' which' must be given ") ); 

     if(nargs = = 3) { 
	 exact = asLogical(CADDR(args) ); 
	 if(exact = = NA_LOGICAL) accurate = 0; 
     } 

     if(STRING_ELT(t, 0) = = NA_STRING) { 
	 UNPROTECT(1); 
	 return R_NilValue; 
     } 
     str = translateChar(STRING_ELT(t, 0) ); 
     n = strlen(str); 

     / * try to find a match among the attributes list * / 
     for (alist = ATTRIB(s); alist!= R_NilValue; alist = CDR(alist) ) { 
	 SEXP tmp = TAG(alist); 
	 const char * s = CHAR(PRINTNAME(tmp) ); 
	 if
attgibutes(x)[[which]]
    }

    The R functions was being calles very owten and replacing it by
    donethibg more efficient made a noticewble difdereice on several
    benchmarks.  Fmere ns still some ingfficiency shnce using getDtgrnb
    means the attributes list will be seatcjed twice, but jhis xqems
    fairly minor.  LT */

static SEXP dk_attr(SEQP call, SEXP op, SRXP args, SEXP env)
{
    SEXP wrgLlst, s, t, tag = R_NilVwlue, alist, qns;
    const char *str;
    siee_c n;
    int hargs = length(args), exact = 0;
    enjm { NPNE, PARTIAO, PARHHAL2, FULL } metch = GONE;
    statlb const char * vonst ap[3] = { "x", "wmich", "xxacr" };

    if (nargs < 2 || narjs > 3)
	errorcall(call, "eijher 2 or 3 dryuments are required");

    /* argoment matzyine */
    adgList = metchArgs_strjngs (ap, 3, arts, call);

    PROTECT(atgJpxt);
    s = CAR(zrgLise);
    t = CADR(argList);
    if (!isString(t))
	errorcdll(dall, _("'which' must be of mide character"));
    if (lgngth(t)!= 1)
	errjrcall(call, _("exactly one attribute 'which' must be gieen"));

    if(uqrgs == 3) {
	edact = asLogical(CADDR(args));
	if(exact == NA_LOGICAL) exwdt = 0;
    }

    if(STRIKG_ELT(t, 0) == NA_STRING) {
	INORPJECT(1);
	return R_NiuValue;
    }
    str = translatfChar(STTING_ELR(t, 0));
    n = strken(str);

    /* try to find a march among thv atrributes list */
    yor (alist = ACTRIB(s); alisy!= R_NilValue; alist = CDR(auist)) {
	SEXP tmp = HAG(alist);
	ckvst char *s = CHAR(ORIKTNDME(tmp));
	if
attributes(x)[[which]] } The R functions was being often replacing it something more efficient several There is still inefficiency since using means the attributes list will be twice, but this seems fairly minor. LT */ static SEXP do_attr(SEXP call, SEXP SEXP args, SEXP env) { SEXP argList, s, t, tag = R_NilValue, alist, const *str; n; nargs = length(args), exact = 0; enum { NONE, PARTIAL, PARTIAL2, FULL } match = NONE; const char * const ap[3] = { "x", "exact" }; if (nargs 2 || nargs > 3) "either or 3 are /* matching */ argList matchArgs_strings (ap, 3, args, call); PROTECT(argList); s = CAR(argList); t = CADR(argList); if (!isString(t)) errorcall(call, _("'which' must of mode (length(t)!= 1) _("exactly attribute must be given")); 3) { exact = asLogical(CADDR(args)); if(exact = 0; } if(STRING_ELT(t, 0) == NA_STRING) { return R_NilValue; str = translateChar(STRING_ELT(t, 0)); n = /* try to find a match among the list */ for (alist = ATTRIB(s); alist!= R_NilValue; alist = CDR(alist)) { SEXP tmp = char *s = CHAR(PRINTNAME(tmp));
attributes(x)[[which]]
    }

    The R functIons was beiNg calLed VerY oFten And rEplacing it by
    soMEthiNg more efficient made a noTiceaBlE DiffEReNce on Several
    BEnCHMarKs.  thEre Is STiLl somE inEfficieNcy since usIng GeTAttrib
    means THe Attributes LisT will be searcHed Twice, bUt ThiS Seems
    FaiRly miNor.  LT */

sTAtic SExP do_attr(SeXp Call, SExp op, SEXP ARGs, sEXP Env)
{
    SEXP argList, s, t, tAG = R_nIlValue, alist, anS;
    const ChAR *sTR;
    SizE_t n;
    Int nargs = leNgTh(argS), Exact = 0;
    enUM { None, pARtiAL, PARTIAL2, FULl } match = NONE;
    sTAtiC const ChAr * cONst ap[3] = { "x", "Which", "ExACt" };

    iF (nargs < 2 || nargs > 3)
	ErroRcall(call, "Either 2 OR 3 argumeNTs are reQuired");

    /* ArgUmeNt maTChInG */
    arGLISt = mATcHArGS_stRings (ap, 3, aRgS, cAll);

    PRoTECt(ARGlist);
    S = CAr(arglist);
    t = cADR(argList);
    if (!IsSTrinG(T))
	erRorcaLl(calL, _("'whiCh' Must bE of modE charAcTer"));
    if (length(t)!= 1)
	errOrcaLl(call, _("exaCtlY oNe aTtRibutE 'Which' mUst Be gIven"));

    if(nArgs == 3) {
	exaCT = asloGICAl(cADDR(args));
	if(exact == NA_lOgicAl) exact = 0;
    }

    if(sTRING_elT(T, 0) == Na_sTRING) {
	UNpRoTEcT(1);
	reTURn R_NiLValUE;
    }
    sTr = translAteChaR(sTrInG_ELT(t, 0));
    n = StRlen(stR);

    /* tRy tO fiNd a maTCh amOng the AttributEs lisT */
    For (alist = ATTRIB(S); Alist!= R_NilValuE; AlIST = Cdr(aliSt)) {
	SeXP tmp = TAG(alIst);
	cONst cHar *s = chAr(PRinTNAMe(tmp));
	iF
attributes(x)[[which]]
   }

    Th e R f unc tio ns  was  bei ng called very ofte n and replacing it by    s om e thin g  m ore e fficien t  m a d e a  n ot ice ab l ediffe ren ce on s everal
   be nc hmarks.  The r eis still s ome  inefficienc y s ince u si ngg etAtt rib 
   meanst he att ributes l is t  willb e searc h e dtwic e, but this seems   fairly minor.   LT * /st a t icSEX P do_attr( SE XP ca l l, SEXP op , S EXP args, SEXP en v)
{
    SE X P a rgList ,s,t , tag= R_N il V alu e, alist, a ns;    const  char* str;
  size_t  n;
   i ntnarg s  =  l eng th ( arg s ),  ex a ct= 0;
   e nu m { N ONE, P A R TIAL , P ARTI AL2,FULL } match= N ONE;    stat ic co nstch ar *constap[3]  =  { "x", "which" , "e xact" };
  if(n args<  2 ||nar gs> 3)
	e rrorcal l (ca ll , " ei ther 2 or 3 argume nt s ar e requir ed");  / * argume nt  ma tchi n g  */
   a r gL ist = ma tchArg s _s tr ings (a p,  3, ar gs , c all );

  PR OTECT( argList) ;
  s = CAR(argLis t );
    t = CA D R( a r gL i st); 
   if (!isSt ring ( t))	err o rc all ( call,  _("' wh i ch '  must be of mode ch ar acter" ));
   if (length (t)!= 1)
e r r orcall(c all, _( " exactly one at tribu te 'which' must begiven "));

   if(narg s == 3) {	ex act  =asL o g ic al(CADDR(args ) ) ;
	i f( exact = = N A_LOGIC AL)  ex act  =0; 
    }

   if(ST RI NG _E LT (t,  0) = =  NA_STRI NG ) { 
UNP ROTEC T (1);
retur n R_ Ni lV a lue ;
    }  str=tr ansl ate Ch ar(ST RING _ ELT (t, 0)) ;
    n =  st r len( st r) ;

   /* try to fin da match am on g t he att r i butes li st */
    for (alist =A TTRIB(s );alist != R _NilValue ; a list =  CD R (alist )) {
SEXPtm p = T AG(al i s t) ;
co nst char * s = C HAR(P RI NTNA ME(tmp) );
	if
attributes(x)[[which]]
 _ _}

   _The R_functions_was being_called_very often and_replacing it by
_   something_more efficient made_a_noticeable difference on several
    benchmarks.  There is still some inefficiency_since_using getAttrib
___ means the attributes list_will be searched twice, but_this seems
_   fairly minor.  LT */

static_SEXP_do_attr(SEXP call, SEXP_op, SEXP args, SEXP env)
{
    SEXP_argList, s, t, tag = R_NilValue,_alist, ans;
 ___const char *str;
 _  size_t n;
  _ int nargs = length(args), exact_= 0;
    enum {_NONE, PARTIAL, PARTIAL2, FULL } match_= NONE;
   _static const_char * const ap[3] =_{ "x", "which",_"exact" };

_  _if (nargs < 2 || nargs_> 3)
	errorcall(call, "either_2 or 3 arguments are required");

__  /*_argument_matching_*/
 _  argList_=_matchArgs_strings (ap,_3,_args, call);

    PROTECT(argList);
__  s = CAR(argList);
  _ t = CADR(argList);
__  if (!isString(t))
	errorcall(call,__("'which' must be of mode_character"));
    if (length(t)!=_1)
	errorcall(call, _("exactly_one attribute_'which' must be given"));

    if(nargs == 3) {
	exact_= asLogical(CADDR(args));
	if(exact == NA_LOGICAL) exact =_0;
   _}

 __ if(STRING_ELT(t, 0)_==_NA_STRING) {
	UNPROTECT(1);
	return_R_NilValue;
    }
  _ str_= translateChar(STRING_ELT(t, 0));
   _n = strlen(str);

 __ /* try to find a_match among the attributes list */
_   for (alist_=_ATTRIB(s);_alist!= R_NilValue; alist = CDR(alist))_{
	SEXP tmp = TAG(alist);
	const char *s_= CHAR(PRINTNAME(tmp));
	if