Fork me on GitHub

root/lib/printk.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. puts
  2. do_printk
  3. register_console
  4. printk
  5. sprintk

   1 /*
   2  * fiwix/lib/printk.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/kernel.h>
   9 #include <fiwix/tty.h>
  10 #include <fiwix/stdio.h>
  11 #include <fiwix/string.h>
  12 #include <fiwix/stdarg.h>
  13 
  14 #define LOG_BUF_LEN     4096
  15 #define MAX_BUF         1024    /* printk() and sprintk() size limit */
  16 
  17 static char log_buf[LOG_BUF_LEN];
  18 static unsigned int log_count;
  19 
  20 static void puts(char *buffer)
  21 {
  22         struct tty *tty;
  23         unsigned short int count;
  24         char *b;
  25 
  26         tty = get_tty(_syscondev);
  27         count = strlen(buffer);
  28         b = buffer;
  29 
  30         while(count--) {
  31                 if(!tty) {
  32                         if(log_count < LOG_BUF_LEN) {
  33                                 log_buf[log_count++] = *(b++);
  34                         }
  35                 } else {
  36                         tty_queue_putchar(tty, &tty->write_q, *(b++));
  37 
  38                         /* kernel messages must be shown immediately */
  39                         tty->output(tty);
  40                 }
  41         }
  42 }
  43 
  44 /*
  45  * format identifiers
  46  * --------------------------------------------------------
  47  *      %d      decimal conversion
  48  *      %u      unsigned decimal conversion
  49  *      %x      hexadecimal conversion (lower case)
  50  *      %X      hexadecimal conversion (upper case)
  51  *      %b      binary conversion
  52  *      %o      octal conversion
  53  *      %c      character
  54  *      %s      string
  55  *
  56  * flags
  57  * --------------------------------------------------------
  58  *      0       result is padded with zeros (e.g.: '%06d')
  59  *              (maximum value is 32)
  60  *      blank   result is padded with spaces (e.g.: '% 6d')
  61  *              (maximum value is 32)
  62  *      -       the numeric result is left-justified
  63  *              (default is right-justified)
  64  */
  65 static void do_printk(char *buffer, const char *format, va_list args)
  66 {
  67         char sw_neg, in_identifier, n_pad, lf;
  68         char ch_pad, basecase, c;
  69         char str[] = {
  70                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  71                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  72                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  73                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  74                 NULL
  75         };
  76         char nullstr[7] = { '<', 'N', 'U', 'L', 'L', '>', '\0' };
  77         char *ptr_s, *p;
  78         int num, count;
  79         char simplechar;
  80         unsigned int unum, digit;
  81 
  82         sw_neg = in_identifier = n_pad = lf = 0;
  83         count = 0;
  84         basecase = 'A';
  85         ch_pad = ' ';
  86         p = NULL;
  87 
  88         /* assumes buffer has a maximum size of MAX_BUF */
  89         while((c = *(format++)) && count < MAX_BUF) {
  90                 if((c != '%') && !in_identifier) {
  91                         *(buffer++) = c;
  92                         memset_b(str, NULL, 32);
  93                 } else {
  94                         in_identifier = 1;
  95                         switch(c = *(format)) {
  96                                 case 'd':
  97                                         num = va_arg(args, int);
  98                                         if(num < 0) {
  99                                                 num *= -1;
 100                                                 sw_neg = 1;
 101                                         }
 102                                         ptr_s = str;
 103                                         do {
 104                                                 *(ptr_s++) = '0' + (num % 10);
 105                                         } while(num /= 10);
 106                                         if(lf) {
 107                                                 p = ptr_s;
 108                                         } else {
 109                                                 while(*ptr_s) {
 110                                                         ptr_s++;
 111                                                 }
 112                                         }
 113                                         if(sw_neg) {
 114                                                 sw_neg = 0;
 115                                                 *(ptr_s++) = '-';
 116                                         }
 117                                         do {
 118                                                 *(buffer++) = *(--ptr_s);
 119                                                 count++;
 120                                         } while(ptr_s != str && count < MAX_BUF);
 121                                         if(lf) {
 122                                                 while(*p && count < MAX_BUF) {
 123                                                         *(buffer++) = *(p++);
 124                                                         count++;
 125                                                 }
 126                                         }
 127                                         format++;
 128                                         ch_pad = ' ';
 129                                         n_pad = 0;
 130                                         in_identifier = 0;
 131                                         lf = 0;
 132                                         break;
 133 
 134                                 case 'u':
 135                                         unum = va_arg(args, unsigned int);
 136                                         ptr_s = str;
 137                                         do {
 138                                                 *(ptr_s++) = '0' + (unum % 10);
 139                                         } while(unum /= 10);
 140                                         if(lf) {
 141                                                 p = ptr_s;
 142                                         } else {
 143                                                 while(*ptr_s) {
 144                                                         ptr_s++;
 145                                                 }
 146                                         }
 147                                         do {
 148                                                 *(buffer++) = *(--ptr_s);
 149                                                 count++;
 150                                         } while(ptr_s != str && count < MAX_BUF);
 151                                         if(lf) {
 152                                                 while(*p && count < MAX_BUF) {
 153                                                         *(buffer++) = *(p++);
 154                                                         count++;
 155                                                 }
 156                                         }
 157                                         format++;
 158                                         ch_pad = ' ';
 159                                         n_pad = 0;
 160                                         in_identifier = 0;
 161                                         lf = 0;
 162                                         break;
 163 
 164                                 case 'x':
 165                                         basecase = 'a';
 166                                 case 'X':
 167                                         unum = va_arg(args, unsigned int);
 168                                         ptr_s = str;
 169                                         do {
 170                                                 *(ptr_s++) = (digit = (unum & 0x0F)) > 9 ? basecase + digit - 10 : '0' + digit;
 171                                         } while(unum /= 16);
 172                                         if(lf) {
 173                                                 p = ptr_s;
 174                                         } else {
 175                                                 while(*ptr_s) {
 176                                                         ptr_s++;
 177                                                 }
 178                                         }
 179                                         do {
 180                                                 *(buffer++) = *(--ptr_s);
 181                                                 count++;
 182                                         } while(ptr_s != str && count < MAX_BUF);
 183                                         if(lf) {
 184                                                 while(*p && count < MAX_BUF) {
 185                                                         *(buffer++) = *(p++);
 186                                                         count++;
 187                                                 }
 188                                         }
 189                                         format++;
 190                                         ch_pad = ' ';
 191                                         n_pad = 0;
 192                                         in_identifier = 0;
 193                                         lf = 0;
 194                                         break;
 195 
 196                                 case 'b':
 197                                         num = va_arg(args, unsigned int);
 198                                         if(num < 0) {
 199                                                 num *= -1;
 200                                         }
 201                                         ptr_s = str;
 202                                         do {
 203                                                 *(ptr_s++) = '0' + (num % 2);
 204                                         } while(num /= 2);
 205                                         if(lf) {
 206                                                 p = ptr_s;
 207                                         } else {
 208                                                 while(*ptr_s) {
 209                                                         ptr_s++;
 210                                                 }
 211                                         }
 212                                         do {
 213                                                 *(buffer++) = *(--ptr_s);
 214                                                 count++;
 215                                         } while(ptr_s != str && count < MAX_BUF);
 216                                         if(lf) {
 217                                                 while(*p && count < MAX_BUF) {
 218                                                         *(buffer++) = *(p++);
 219                                                         count++;
 220                                                 }
 221                                         }
 222                                         format++;
 223                                         ch_pad = ' ';
 224                                         n_pad = 0;
 225                                         in_identifier = 0;
 226                                         lf = 0;
 227                                         break;
 228 
 229                                 case 'o':
 230                                         num = va_arg(args, unsigned int);
 231                                         if(num < 0) {
 232                                                 num *= -1;
 233                                         }
 234                                         ptr_s = str;
 235                                         do {
 236                                                 *(ptr_s++) = '0' + (num % 8);
 237                                         } while(num /= 8);
 238                                         if(lf) {
 239                                                 p = ptr_s;
 240                                         } else {
 241                                                 while(*ptr_s) {
 242                                                         ptr_s++;
 243                                                 }
 244                                         }
 245                                         do {
 246                                                 *(buffer++) = *(--ptr_s);
 247                                                 count++;
 248                                         } while(ptr_s != str && count < MAX_BUF);
 249                                         if(lf) {
 250                                                 while(*p && count < MAX_BUF) {
 251                                                         *(buffer++) = *(p++);
 252                                                         count++;
 253                                                 }
 254                                         }
 255                                         format++;
 256                                         ch_pad = ' ';
 257                                         n_pad = 0;
 258                                         in_identifier = 0;
 259                                         lf = 0;
 260                                         break;
 261 
 262                                 case 'c':
 263                                         simplechar = va_arg(args, int);
 264                                         *(buffer++) = simplechar;
 265                                         format++;
 266                                         in_identifier = 0;
 267                                         lf = 0;
 268                                         break;
 269 
 270                                 case 's':
 271                                         num = 0;
 272                                         ptr_s = va_arg(args, char *);
 273                                         if(n_pad) {
 274                                                 num = n_pad - strlen(ptr_s);
 275                                                 if(num < 0) {
 276                                                         num *= -1;
 277                                                 }
 278                                         }
 279                                         /* if it's a NULL then show "<NULL>" */
 280                                         if(ptr_s == NULL) {
 281                                                 ptr_s = (char *)nullstr;
 282                                         }
 283                                         while((c = *(ptr_s++)) && count < MAX_BUF) {
 284                                                 *(buffer++) = c;
 285                                                 count++;
 286                                         }
 287                                         while(num-- && count < MAX_BUF) {
 288                                                 *(buffer++) = ' ';
 289                                                 count++;
 290                                         }
 291                                         format++;
 292                                         n_pad = 0;
 293                                         in_identifier = 0;
 294                                         lf = 0;
 295                                         break;
 296 
 297                                 case ' ':
 298                                         ch_pad = ' ';
 299                                         break;
 300 
 301                                 case '0':
 302                                         if(!n_pad) {
 303                                                 ch_pad = '0';
 304                                         }
 305                                 case '1':
 306                                 case '2':
 307                                 case '3':
 308                                 case '4':
 309                                 case '5':
 310                                 case '6':
 311                                 case '7':
 312                                 case '8':
 313                                 case '9':
 314                                         n_pad = !n_pad ? c - '0': ((n_pad * 10) + (c - '0'));
 315                                         n_pad = n_pad > 32 ? 32 : n_pad;
 316                                         for(unum = 0; unum < n_pad; unum++) {
 317                                                 str[unum] = ch_pad;
 318                                         }
 319                                         break;
 320 
 321                                 case '-':
 322                                         lf = 1;
 323                                         break;
 324                                 case '%':
 325                                         *(buffer++) = c;
 326                                         format++;
 327                                         in_identifier = 0;
 328                                         break;
 329                         }
 330                 }
 331                 count++;
 332         }
 333         *buffer = NULL;
 334 }
 335 
 336 void register_console(void (*fn)(char *, unsigned int))
 337 {
 338         (*fn)(log_buf, log_count);
 339 }
 340 
 341 void printk(const char *format, ...)
 342 {
 343         va_list args;
 344         char buffer[MAX_BUF];
 345 
 346         va_start(args, format);
 347         do_printk(buffer, format, args);
 348         puts(buffer);
 349         va_end(args);
 350 }
 351 
 352 int sprintk(char *buffer, const char *format, ...)
 353 {
 354         va_list args;
 355 
 356         va_start(args, format);
 357         do_printk(buffer, format, args);
 358         va_end(args);
 359         return strlen(buffer);
 360 }

/* [previous][next][first][last][top][bottom][index][help] */