From: "Alexei A. Frounze" 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" wrote in message news:9598k2$nn0$1 AT nets3 DOT rz DOT RWTH-Aachen DOT DE... > Christian Merz 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 "" 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.