Ergänzungen zum C-Buch

Copyright © 1985,2006  Helmut O.B. Schellong

C99 Padding bits

Aus Quellcode-Library:


#if defined(F_catstr) && !defined(DF_catstr) && !defined(catstr)
# define DF_catstr
fSTATIC int catstr(BYTE *S0, const BYTE *S1, ...)
{
   BYTE *s;
   if (s=S0, s)  {
     if (!S1)  while (*s)  ++s;
     else  { const BYTE *sa=S1; va_list a;
       va_start(a,S1);
       do  while (!!(*s=*sa))  ++s,++sa;
       while (sa=va_arg(a,BYTE*),  sa);
       va_end(a);
     }
   }
   return (int)(s-S0);
}
#endif
Verkettet Strings ab S1, Zielpuffer ist S0.
Liefert Stringlänge des S0, auch bei S1==0.
Abschlußargument: (BYTE*)0

#if defined(F_catstrn) && !defined(DF_catstrn) && !defined(catstrn)
# define DF_catstrn
#if defined(BSH_H) && !defined(catstrnEXIT)
# define catstrnEXIT()  bsh_Err(E_LIMIT, "Ziel-Puffer");
#endif
#if !defined(catstrnEXIT)
# define catstrnEXIT()  write(2, "*** LIMIT: Ziel-Puffer ***\r\n", 28), exit(64);
#endif
fSTATIC int catstrn(int n, BYTE *S0, const BYTE *S1, ...)
{
   BYTE *s;
   if (s=S0, s&&n>0)  { const BYTE *sa; va_list a;
     va_start(a,S1);
     for (sa=S1;  sa;  ++n,sa=va_arg(a,BYTE*))  {
        while (n-- >0 && !!(*s=*sa))  ++s,++sa;
        if (n<0)  {
          va_end(a);
          catstrnEXIT();
          return n;
        }
     }
     va_end(a);
   }
   return (int)(s-S0);
}
#endif
Fast wie catstr(). Mit zusätzlicher Prüfung der Zielpuffergröße.

#if defined(F_printi) && !defined(DF_printi) && !defined(printi)
# define DF_printi
# include <stdarg.h>
fSTATIC int printi(const BYTE *F, ...)
{
   BYTE buf[4*1024];
   va_list ap;
   int r, fd;
   if (!F)  return -1;
   va_start(ap,F);
   if (F[0]=='%'&&F[1]=='H')  {
     F+=2; fd=va_arg(ap,int);
     if (fd<0)  { va_end(ap); return -1; }
   }
   else  fd=1;
   r= sprinti(buf, "\004%B%F%V", sizeof(buf), F, ap);
   va_end(ap);
   if (r>0)  write(fd, buf, r);
   return r;
}
#endif
Ähnelt printf(). Verarbeitet nur Integer.
Benutzt nachfolgende sprinti(), die informiert wird, falls von printi() Aufruf erfolgt.
Format %H ganz zu Beginn gestattet Angabe eines Filedescriptor (Handle / fd). Andernfalls ist fd=1, wie bei printf().
Zielpuffergröße 4KB wird von sprinti() berücksichtigt.

#if defined(F_sprinti) && !defined(DF_sprinti) && !defined(sprinti)
# define DF_sprinti
#if defined(BSH_H) && !defined(sprintiEXIT)
# define sprintiEXIT()  bsh_Err(E_LIMIT, "Ziel-Puffer");
#endif
#if !defined(sprintiEXIT)
# define sprintiEXIT()  write(2, "*** LIMIT: Ziel-Puffer ***\r\n", 28), exit(64);
#endif
# include <stdarg.h>
# define LINKS     1
# define VPLUS     2
# define VLEER     4
# define V0X       8
# define VNULL    16
# define GLEIT    32
# define LCUT     64
# define ISWI    512
# define ISPR   1024
# define LENH   2048
# define LENL   4096
# define LENLL  0x4000
# define NOINT  0x2000
# define CENTR  0x8000u
# define NEGAT   128
# define XUPP    256
fSTATIC int sprinti(BYTE *buf, const BYTE *f, ...)
{
   BYTE *b;
   int blen=(1<<30)-1;
   va_list ap, ap0;
   if (!(b=buf)||!f)  return -1;
   va_start(ap,f); va_copy(ap0,ap);
   if (f[0]==4&&f[1]=='%'&&f[2]=='B'&&f[3]=='%'&&f[4]=='F'&&f[5]=='%'&&f[6]=='V')  {
     blen= (int)va_arg(ap0,size_t);
     f   = va_arg(ap0,BYTE*);
     ap  = va_arg(ap0,va_list);
   }
   else  if (f[0]=='%'&&f[1]=='B')  f+=2, blen=(int)va_arg(ap,size_t);
   va_end(ap0);
   if (blen<=0||blen==1&&(*b=0,1))  { va_end(ap); return 0; }
   while (*f)  { BYTE ns[132], fs[4]; BYTE *s;
                 UNS flg, z; int l, w, p;
      if (*f!='%' || f[1]=='%'&&(++f,1) || f[1]==0)  {
        if (blen<=1)  va_end(ap), sprintiEXIT();
        *b++= *f++; --blen; continue;
      }
      for (s=0,++f,w=p=0,flg=z=0;  z<=4&&*f;  ++z)  {
         switch (z)  {
           case 0:
                    NXTF:;
                    switch (*f)  {
                      case '-':  flg|= LINKS; break;
                      case '+':  flg|= VPLUS; break;
                      case ' ':  flg|= VLEER; break;
                      case '#':  flg|=   V0X; break;
                      case '0':  flg|= VNULL; break;
                      case ',':  flg|= GLEIT; break;
                      case '|':  flg|=  LCUT; break;
                      case ':':  flg|= CENTR; break;
                      default :  continue;
                    }
                    ++f; goto NXTF;
           case 1:
                    if (*f=='*')  flg|=ISWI, ++f, w= va_arg(ap,int);
                    else          if (DIGIT(*f))  { flg|=ISWI;
                                    w= atoi_F(f);
                                    while (DIGIT(*f))  ++f;
                                  }
                    if (w<0)  w=-w, flg|=LINKS;
                    if (*f!='.')  { z=3-1; continue; }
                    break;
           case 2:
                    if (DIGIT(*f)||*f=='*')  { flg|=ISPR;
                      if (*f=='*')  p= va_arg(ap,int), ++f;
                      else        { p= atoi_F(f);
                                    while (DIGIT(*f))  ++f; }
                    }
                    else  continue;
                    z=3;
           case 3:
                    if (*f=='h')  { flg|=LENH; break; }
                    if (*f=='l')  { flg|= f[1]=='l'?(++f,LENLL):LENL; break; }
                    continue;
           case 4:
               switch (s=ns,l=0,  *f)  { INT8 sv; UNS8 uv;
                 case 'i':
                 case 'd':  if (flg&LENLL)  sv= va_arg(ap,INT8);
                            else  if (flg&LENL)
                                            sv= va_arg(ap,INT4);
                            else  if (flg&LENH)
                                            sv= va_arg(ap,INT);
                            else            sv= va_arg(ap,INT);
                            if (sv<0L)  sv=-sv, flg|=NEGAT;
                            if (flg&LENLL)  l=ulltoa_F(ns, sv);
                            else  if (flg&LENL)
                                            l= ultoa_F(ns, (UNS4)sv);
                            else  if (flg&LENH)
                                            l=  utoa_F(ns, (UNS)sv);
                            else            l=  utoa_F(ns, (UNS)sv);
                            break;
                 case 'u':
                            if (flg&LENLL)  l=ulltoa_F(ns, va_arg(ap,UNS8));
                            else  if (flg&LENL)
                                            l= ultoa_F(ns, va_arg(ap,UNS4));
                            else  if (flg&LENH)
                                            l=  utoa_F(ns, va_arg(ap,UNS));
                            else            l=  utoa_F(ns, va_arg(ap,UNS));
                            break;
                 case 'x':
                 case 'X':
                 case 'b':  if (flg&LENLL)  uv= va_arg(ap,UNS8);
                            else  if (flg&LENL)
                                            uv= va_arg(ap,UNS4);
                            else  if (flg&LENH)
                                            uv= va_arg(ap,UNS);
                            else            uv= va_arg(ap,UNS);
                            if (*f=='b')  l= ulltob_F(ns, uv);
                            else          l= ulltoh_F(ns, uv);
                            if (*f=='X')  toupp_F(ns), flg|=XUPP;
                            break;
                 case 'n':  *( va_arg(ap,int*) )= (int)(b-buf);
                            flg|=NOINT; s=0;
                            break;
                 case 's':  s= va_arg(ap,BYTE*);
                            if (!s)  s="(null)";
                            while (s[l])  ++l;
                            flg|=NOINT;
                            break;
                 case 'c':  ns[0]= (BYTE)va_arg(ap,int);
                            flg|=NOINT; l=1;
                            break;
                 default :  z=0; goto FERR;
               }
               break;
           default: continue;
         }
         ++f;
      }
      /*for-z*/
      FERR:;
      if (s&&z==5)  { int lfs, l0, wfill, sp,spv;
                      BYTE *f0;
        spv=sp=wfill=l0=lfs=0;
        if (!(flg&NEGAT))  {
          if (flg& VPLUS)  fs[0]='+', lfs=1;
          if (flg& VLEER)  fs[0]=' ', lfs=1;
        }
        else  fs[0]='-', ++lfs;
        if (flg& V0X)  fs[lfs++]='0', fs[lfs++]= flg&XUPP?'X':'x';

        if ((flg&(GLEIT|NOINT|ISPR))==(GLEIT|ISPR))  {
          if (f0=s,z=p,  p>l)  z=l, sp=p-l;
          for (s+=l       ;  z;  --s,--z)  s[sp]= s[-1];
          for (*s='.',z=sp;  z;      --z)  s[z ]= '0';
          if (p=l+=sp+1,  s==f0)  ++p;
          s=f0; sp=0;
        }

        if (!(flg&NOINT))  { if (flg&ISPR&&p>l)  l0=p-l; }
        else               { if (flg&ISPR&&l>p)  l =p  ; }
        if ((flg&(LCUT|ISWI))==(LCUT|ISWI) && lfs+l0+l>w)  {
          if (l0 =w-(lfs+l ),  l0 <0)  l0 =0;
          if (lfs=w-(l  +l0),  lfs<0)  lfs=0;
          if (l  =w-(lfs+l0),  l  <0)  l  =0;
        }
        if (flg&ISWI)  wfill= w - (lfs+l0+l);
        if (wfill>0)  {
          if (flg&VNULL)  l0+=wfill;
          else  if (flg&CENTR)  spv=wfill>>1, sp=wfill-spv;
                else  if (flg&LINKS)  sp =wfill;
                      else            spv=wfill;
        }
        blen-= spv+lfs+l0+l+sp;
        if (blen<1)  va_end(ap), sprintiEXIT();
        while (spv>0)  *b++=' ', --spv;
        for (z=0;  lfs>0;  --lfs)  *b++= fs[z++];
        while (l0 >0)  *b++='0', --l0;
        while (l  >0)  *b++= *s++, --l;
        while (sp >0)  *b++=' ', --sp;
      }
   }
   va_end(ap);
   *b=0;
   return b-buf;
}
#undef LINKS
#undef VPLUS
#undef VLEER
#undef V0X
#undef VNULL
#undef GLEIT
#undef LCUT
#undef ISWI
#undef ISPR
#undef LENH
#undef LENL
#undef LENLL
#undef NOINT
#undef CENTR
#undef NEGAT
#undef XUPP
#undef DIGIT
#undef LOWER
#endif