delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2001/01/31/11:36:37

From: "Alexei A. Frounze" <dummy_addressee AT hotmail DOT com>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: va_list args
Date: Wed, 31 Jan 2001 11:23:04 -0500
Lines: 508
Message-ID: <959e3d$g51qv$1@ID-57378.news.dfncis.de>
References: <9593n9$4lb$1 AT snoopy DOT bndlg DOT de> <9598k2$nn0$1 AT nets3 DOT rz DOT RWTH-Aachen DOT DE>
NNTP-Posting-Host: ip78.rochester6.ny.pub-ip.psi.net (38.26.84.78)
X-Trace: fu-berlin.de 980958128 16942943 38.26.84.78 (16 [57378])
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 5.50.4133.2400
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

That's right. I do the following thing (skip irrelevant code and see prinf()
implementation):
---------8<----------
////////////////////////
// CONIO.H/LIB MODULE //
////////////////////////

#include "conio.h"
//#include "string.h"
#include "ints.h"
#include "ports.h"

                        /* INNER DATA */

byte    *_screen_base = (byte *) 0xB8000;
dword    _cursor_x = 0, _cursor_y = 0;
dword    _scrolling = 1;
byte     _textattr = 7;
volatile byte  _keybuf[_KEYBUF_SIZE];
volatile dword _kbhead = 0, _kbtail = 0, _kbcnt = 0;

byte     _symmap[256] =
  {"\0\0331234567890-=\b\tQWERTYUIOP[]\r\0ASDFGHJKL;\'`\0\\ZXCVBNM,./\0*\0
"};
  // \0 - zero
  // \033 - esc (octal 33 = decimal 27 )
  // \b - backspace
  // \t - tab
  // \r - return - enter
  // \\ - "\"

                        /* FUNCTIONS */

// Updates location of a hardware text cursor
void _update_cursor() {
  dword offs = _cursor_y*80+_cursor_x;
  outportb (0x3D4, 0x0F); outportb (0x3D5, offs & 0xFF);
  offs>>=8;
  outportb (0x3D4, 0x0E); outportb (0x3D5, offs & 0xFF);
}

// Must be run first
void conio_init() {
  byte *eq = (byte *) 0x410;

  // let's find out wether screen is color or mono and find
  // appropriate value for the screen pointer
  if (((*eq) & 0x30) == 0x30) _screen_base = (byte *) 0xB0000;
  else _screen_base = (byte *) 0xB8000;

  _textattr = 7;
  _cursor_x = _cursor_y = 0;
  _update_cursor();
}

// Locates the cursor
void gotoxy (dword x, dword y) {
  _cursor_x = x;
  _cursor_y = y;
  _update_cursor();
}

// Reads cursor X
dword wherex() {
  return _cursor_x;
}

// Reads cursor Y
dword wherey() {
  return _cursor_y;
}

// Sets foreground color
void textbackground (byte color) {
  _textattr = (_textattr & 0x0F) | (color << 4);
}

// Sets ink color
void textcolor (byte color) {
  _textattr = (_textattr & 0xF0) | (color & 0x0F);
}

// Clears the screen with current color (_textattr)
void clrscr() {
  __asm__ __volatile__ ("
    movl    %1, %%edi
    movl    $80*25, %%ecx
    movb    %0, %%ah
    movb    $0, %%al
    cld
    rep
    stosw"
    :
    : "g" (_textattr), "g" (_screen_base)
    : "eax", "ecx", "edi"
  );
  gotoxy (0, 0);
}

// Inner routine - do not use!
void __scroll() {
  byte *s;
  int i;

  memcpy (_screen_base, _screen_base+80*2, 80*24*2);
  s = _screen_base + 80*24*2;
  for (i=0;i<80;i++) {
    *s++ = 0;
    *s++ = _textattr;
  }
}

// Inner routine - do not use!
void __putch (char c) {
  dword offs = (_cursor_x + _cursor_y*80)*2;
  _screen_base[offs] = c;
  _screen_base[offs+1] = _textattr;
}

// Puts a character to the screen (adjusts cursor position)
// Few control characters available:
// \t, \n, \r, \b
void putch (char c) {
  switch (c) {
    case '\t' :
      do {
        __putch (' ');
        if (++_cursor_x>=80) {
          _cursor_x = 0;
          if (++_cursor_y>=25) {
            if (_scrolling) {
              _cursor_y=24;
              __scroll();
            } else
              _cursor_y = 0;
          };
        };
      } while (_cursor_x % 8);
    break;
    case '\n' :
      if (++_cursor_y>=25) {
        if (_scrolling) {
          _cursor_y=24;
          __scroll();
        } else
          _cursor_y = 0;
      };
    break;
    case '\r' :
      _cursor_x = 0;
    break;
    case '\b' :
      if (_cursor_x > 0) _cursor_x--;
    break;
    default:
      __putch (c); _cursor_x++;
    break;
  };

  if (_cursor_x>=80) {
    _cursor_x = 0;
    if (++_cursor_y>=25) {
      if (_scrolling) {
        _cursor_y=24;
        __scroll();
      } else
        _cursor_y = 0;
    };
  };
  _update_cursor();
}

/*
   printf() stuff
                  */

/* Inner routine - do not use! */
void __puts (char *s, int len, int zero) {
  int l=0;
  char *p;

  p=s;
  while (*p++) l++;             /* strlen(s) */

  while (len > l) {             /* left-padded */
    if (zero) putch ('0');
    else putch (0x20);
    len--;
  };

  while (*s)
    putch (*s++);

  while (-len > l) {            /* right-padded */
    putch (0x20);
    len++;
  }
}

/* Inner routine - do not use! */
void __putd (int d, int len, int zero) {
  char s[12], *p;
  int neg=0;

  s[11] = 0;
  s[10] = '0';
  p = &s[10];
  if (d<0) {
    neg = 1;
    d =- d;
  };
  if (d) {
    while (d) {
      *p-- = d%10+'0';
      d /= 10;
    };
    p++;
  };
  if (neg) {
    p--;
    *p = '-';
  };
  __puts (p, len, zero);
}

/* Inner routine - do not use! */
void __putud (unsigned int d, int len, int zero) {
  char s[12], *p;

  s[11] = 0;
  s[10] = '0';
  p = &s[10];
  if (d) {
    while (d) {
      *p-- = d%10+'0';
      d /= 10;
    };
    p++;
  };
  __puts (p, len, zero);
}

/* Inner routine - do not use! */
void __puth (unsigned int h, int upper, int len, int zero) {
  char s[12], *p, c;

  s[11] = 0;
  s[10] = '0';
  p = &s[10];
  if (h) {
    while (h) {
      if (upper) { if ((c = h%16 + '0') > '9') c+='A'-'9'-1; }
      else       { if ((c = h%16 + '0') > '9') c+='a'-'9'-1; };
      *p-- = c;
      h /= 16;
    };
    p++;
  };
  __puts (p, len, zero);
}

/* Inner routine - do not use! */
void __putld (long d, int len, int zero) {
  char s[12], *p;
  int neg=0;

  s[11] = 0;
  s[10] = '0';
  p = &s[10];
  if (d<0) {
    neg = 1;
    d =- d;
  };
  if (d) {
    while (d) {
      *p-- = d%10+'0';
      d /= 10;
    };
    p++;
  };
  if (neg) {
    p--;
    *p = '-';
  };
  __puts (p, len, zero);
}

/* Inner routine - do not use! */
void __putlud (unsigned long d, int len, int zero) {
  char s[12], *p;

  s[11] = 0;
  s[10] = '0';
  p = &s[10];
  if (d) {
    while (d) {
      *p-- = d%10+'0';
      d /= 10;
    };
    p++;
  };
  __puts (p, len, zero);
}

/* Inner routine - do not use! */
void __putlh (unsigned long h, int upper, int len, int zero) {
  char s[12], *p, c;

  s[11] = 0;
  s[10] = '0';
  p = &s[10];
  if (h) {
    while (h) {
      if (upper) { if ((c = h%16 + '0') > '9') c+='A'-'9'-1; }
      else       { if ((c = h%16 + '0') > '9') c+='a'-'9'-1; };
      *p-- = c;
      h /= 16;
    };
    p++;
  };
  __puts (p, len, zero);
}

/* Puts a formated ASCIIZ string to the screen (adjusts cursor position) */
/* Currently supports these specifiers:                                  */
/*   %%         for "%",                                                 */
/*   %c         for char                                                 */
/*   %s         for ASCIIZ strings                                       */
/*   %d and %i  for int                                                  */
/*   %u         for unsigned int                                         */
/*   %x and %X  for unsigned int                                         */
/* and these input-size modifiers:                                       */
/*   l          for long int                                             */
/* Supported width specifiers:                                           */
/*   n          for left-padded output   (n>0)                           */
/*  -n          for right-padded output  (n>0)                           */
/*  0n          for 0 left-padded output (n>0)                           */
void printf (const char *fmt, ...) {
  va_list arglist;
  int x=0;
  int is_long;
  int len;
  int neg;
  int zero_pad;
  char          *str;
  int           dec;
  unsigned int  udec;
  unsigned int  hex;
  long          ldec;
  unsigned long ludec;
  unsigned long lhex;

  va_start (arglist, fmt);
  while (fmt[x]) {
    if (fmt[x] == '%') {
      is_long = len = zero_pad = 0;
      neg = 1;
      x++;
      if (fmt[x] == '-') {
        neg = -1;
        x++;
      };
      if (fmt[x] == '0') {
        zero_pad = 1;
        x++;
      };
      while ((fmt[x] >= '0') && (fmt[x] <= '9')) {
        len = len * 10 + (unsigned int)(fmt[x]-'0');
        x++;
      };
      len *= neg;
      if (fmt[x] == 'l') {
        is_long = 1;
        x++;
      };
      switch (fmt[x]) {
        case '%':
          putch ('%');
        break;
        case 's':
          str = va_arg (arglist, char*);
          __puts (str, len, 0);
        break;
        case 'c':
          dec = (int)va_arg (arglist, char);
          putch (dec);
        break;
        case 'd':
        case 'i':
          if (is_long) {
            ldec = va_arg (arglist, long);
            __putld (ldec, len, zero_pad);
          } else {
            dec = va_arg (arglist, int);
            __putd (dec, len, zero_pad);
          };
        break;
        case 'u':
          if (is_long) {
            ludec = va_arg (arglist, unsigned long);
            __putlud (ludec, len, zero_pad);
          } else {
            udec = va_arg (arglist, unsigned int);
            __putud (udec, len, zero_pad);
          };
        break;
        case 'x':
          if (is_long) {
            lhex = va_arg (arglist, unsigned long);
            __putlh (lhex, 0, len, zero_pad);
          } else {
            hex = va_arg (arglist, unsigned int);
            __puth (hex, 0, len, zero_pad);
          };
        break;
        case 'X':
          if (is_long) {
            lhex = va_arg (arglist, unsigned long);
            __putlh (lhex, 1, len, zero_pad);
          } else {
            hex = va_arg (arglist, unsigned int);
            __puth (hex, 1, len, zero_pad);
          };
        break;
        default:
          putch (fmt[x]);
        break;
      };
    } else {
      if (fmt[x] == '\n') {
        putch ('\r');
        putch ('\n');
      } else
        putch (fmt[x]);
    };
    x++;
  };
  va_end (arglist);
}

// Returns non-zero result in case of pressed key
int kbhit() {
  return _kbcnt;
}

// Returns scan code of the pressed key
char getscan() {
  char r;

  while (!_kbcnt) {};
  r = _keybuf[_kbhead++];
  if (_kbhead == _KEYBUF_SIZE) _kbhead = 0;
  _kbcnt--;
  return r;
}

// Returns ASCII code (in upper case) of the pressed key
char getch() {
  return _symmap[(int)getscan()];
}

// Cleans the keyboard buffer
void clear_keybuf() {
  disable();
  _kbhead = _kbtail = _kbcnt=0;
  enable();
}
---------8<----------

--
Alexei A. Frounze
alexfru [AT] chat [DOT] ru
frounze [AT] ece [DOT] rochester [DOT] edu
http://alexfru.chat.ru
http://members.xoom.com/alexfru/
http://welcome.to/pmode/

"Hans-Bernhard Broeker" <broeker AT physik DOT rwth-aachen DOT de> wrote in message
news:9598k2$nn0$1 AT nets3 DOT rz DOT RWTH-Aachen DOT DE...
> Christian Merz <cmerz AT bndlg DOT de> wrote:
> > can anybody tell me how the va_list, va_start() and va_end() works?
>
> Unless you want to re-implement them on your own, in assembly or so,
> you don't need to know how they work. Just how you're supposed to use
> them.
>
> > I have to include the "<stdarg.h>" file, because I'll write my own
> > printf function for my os, but I guess va_list, va_start() and
> > va_end() uses some memory allocation routines for allocating some
> > lists and so on , right?
>
> No memory allocation, no. The arguments have been put on the stack by
> the calling function. All va_start() and friends to is hand them over
> to your code, one by one.
>
> > So what I have to do to get the "va" stuff working?
>
> Just use them. They already do work --- if they don't, you're not done
> yet with porting GCC to that OS :-)
>
> info libc alpha varargs
>
> has all you need to know, I think.
> --
> Hans-Bernhard Broeker (broeker AT physik DOT rwth-aachen DOT de)
> Even if all the snow were burnt, ashes would remain.


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019