- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/modules/dbg/src/dbg_print.c

Go to the documentation of this file.

    00001
    00020 /*
    00021  * INCLUDE FILES
    00022  ****************************************************************************************
    00023  */
    00024 #include <stdarg.h>
    00025
    00026 #include "rwnx_config.h"
    00027 #include "dbg_assert.h"
    00028 #include "co_math.h"
    00029
    00030 #include "dbg.h"
    00031
    00032 #if NX_PRINT == NX_PRINT_IPC
    00033 #include "ipc_emb.h"
    00034 #elif NX_PRINT == NX_PRINT_PRINTF
    00035 #include <stdio.h>
    00036 #elif NX_PRINT == NX_PRINT_PRINTK
    00037 #include <linux/kernel.h>
    00038 #endif
    00039
    00041 #define FLAG_SHORT_SUPPORTED
    00042
    00044 enum
    00045 {
    00046     S_COPY,         // Initial state; copy chars of the format str
    00047     S_PERCENT,      // just read '%'
    00048     S_FLAGS,        // just read flag character
    00049     S_WIDTH,        // just read width specifier
    00050     S_DOT,          // just read '.'
    00051     S_PRECIS,       // just read field_precision specifier
    00052     S_SIZE,         // just read size specifier
    00053     S_TYPE,         // just read type specifier
    00054     S_MAX
    00055 };
    00056
    00058 enum
    00059 {
    00060     C_OTHER,        // character with no special meaning
    00061     C_PERCENT,      // '%'
    00062     C_DOT,          // '.'
    00063     C_ZERO,         // '0'
    00064     C_DIGIT,        // '1'..'9'
    00065     C_FLAG,         // ' ', '+', '-',
    00066     C_SIZE,         // 'h', 'l', 'L'
    00067     C_TYPE,         // type specifying character
    00068     C_MAX
    00069 };
    00070
    00071
    00073 enum
    00074 {
    00075     FLAG_SHORT      = (1 << 0),   // short value
    00076     FLAG_LONG       = (1 << 1),   // long value
    00077     FLAG_SIGNED     = (1 << 2),   // signed value
    00078     FLAG_SIGN       = (1 << 3),   // Add a - or + in the front of the field
    00079     FLAG_SIGN_SPACE = (1 << 4),   // Add a space or - in the front of the field
    00080     FLAG_LEFT       = (1 << 5),   // left justify
    00081     FLAG_LEAD_ZERO  = (1 << 6),   // padding with 0
    00082     FLAG_NEGATIVE   = (1 << 7),   // the value is negative
    00083 };
    00084
    00085
    00087 static const uint8_t transition_table[S_MAX][C_MAX] =
    00088 {   //              OTHER       PERCENT     DOT         ZERO        DIGIT       FLAG        SIZE        TYPE
    00089 /*  S_COPY    */  { S_COPY,     S_PERCENT,  S_COPY,     S_COPY,     S_COPY,     S_COPY,     S_COPY,     S_COPY  },
    00090 /*  S_PERCENT */  { S_COPY,     S_COPY,     S_DOT,      S_FLAGS ,   S_WIDTH,    S_FLAGS ,   S_SIZE,     S_TYPE  },
    00091 /*  S_FLAGS   */  { S_COPY,     S_COPY,     S_DOT,      S_FLAGS,    S_WIDTH,    S_FLAGS,    S_SIZE,     S_TYPE  },
    00092 /*  S_WIDTH   */  { S_COPY,     S_COPY,     S_DOT,      S_WIDTH,    S_WIDTH,    S_COPY,     S_SIZE,     S_TYPE  },
    00093 /*  S_DOT     */  { S_COPY,     S_COPY,     S_COPY,     S_PRECIS,   S_PRECIS,   S_COPY,     S_SIZE,     S_TYPE  },
    00094 /*  S_PRECIS  */  { S_COPY,     S_COPY,     S_COPY,     S_PRECIS,   S_PRECIS,   S_COPY,     S_SIZE,     S_TYPE  },
    00095 /*  S_SIZE    */  { S_COPY,     S_COPY,     S_COPY,     S_COPY,     S_COPY,     S_COPY,     S_COPY,     S_TYPE  },
    00096 /*  S_TYPE    */  { S_COPY,     S_PERCENT,  S_COPY,     S_COPY,     S_COPY,     S_COPY,     S_COPY,     S_COPY  },
    00097 };
    00098
    00099
    00101 static const char hex_upper_table[] = "0123456789ABCDEF";
    00102 #ifdef SUPPORT_LOWER_CASE_HEX
    00104 static const char hex_lower_table[] = "0123456789abcdef";
    00105 #endif
    00106
    00107
    00108
    00120 static uint32_t type_get(char c)
    00121 {
    00122     uint32_t res;
    00123
    00124     switch(c)
    00125     {
    00126     case '%':
    00127         res =  C_PERCENT;
    00128         break;
    00129
    00130     case '.':
    00131         res =  C_DOT;
    00132         break;
    00133
    00134     case '0':
    00135         res =  C_ZERO;
    00136         break;
    00137
    00138     case ' ':
    00139     case '+':
    00140     case '-':
    00141         res =  C_FLAG;
    00142         break;
    00143
    00144     case 'h':
    00145     case 'l':
    00146         res =  C_SIZE;
    00147         break;
    00148
    00149     case 'x':
    00150     case 'X':
    00151     case 'd':
    00152     case 'b':
    00153     case 'i':
    00154     case 'c':
    00155     case 'u':
    00156     case 's':
    00157     case 'm':
    00158     case 'M':
    00159     case 'a':
    00160     case 'A':
    00161         res =  C_TYPE;
    00162         break;
    00163
    00164     case '*':
    00165         res =  C_DIGIT;
    00166         break;
    00167
    00168     default:
    00169         if(('1' <= c) && (c <= '9'))
    00170         {
    00171             res =  C_DIGIT;
    00172         }
    00173         else
    00174         {
    00175             res =  C_OTHER;
    00176         }
    00177         break;
    00178     }
    00179
    00180     return res;
    00181 }
    00182
    00201 uint32_t dbg_vsnprintf_offset(char *buffer, uint32_t size, uint32_t offset, const char *fmt, va_list args)
    00202 {
    00203      uint32_t    state_current = S_COPY;  // Initial state
    00204      char        c;
    00205
    00206      char        *fmt_field_ptr = NULL;
    00207      int         fmt_field_size = 0;
    00208
    00209      char        buffer_tmp[64];
    00210
    00211      int         field_width = 0;
    00212      char        field_flags = 0;
    00213      int         field_precision = 0;
    00214      int         field_padding = 0;
    00215
    00216      int32_t     value;
    00217      char        *tmp_ptr = NULL;
    00218
    00219      uint32_t    res = 0, remain;
    00220
    00221      #define WRITE_CHAR(_c) if (remain && res >= offset) {*buffer++ = (_c); remain--;} res++
    00222
    00223      // Check parameters: If buffer is NULL then size MUST be 0.
    00224      if (buffer == NULL)
    00225          size = 0;
    00226
    00227      remain = size;
    00228
    00229      // For each char in format string
    00230      while ((c = *fmt++) != 0)
    00231      {
    00232          state_current =  transition_table[state_current][type_get(c)];
    00233
    00234          switch (state_current)
    00235          {
    00236          case S_COPY  :
    00237              WRITE_CHAR(c);
    00238              break;
    00239
    00240          case S_PERCENT:
    00241              // Assign default value for the conversion parameters
    00242              field_width = 0;
    00243              field_flags = 0;
    00244              field_precision = -1;
    00245              break;
    00246
    00247          case S_FLAGS:
    00248              // set flag based on which flag character
    00249              switch(c)
    00250              {
    00251              case '-':
    00252                  // left justify
    00253                  field_flags |= FLAG_LEFT;
    00254                  break;
    00255              case '+':
    00256                  // force sign indicator
    00257                  field_flags |= FLAG_SIGN;
    00258                  break;
    00259              case ' ':
    00260                  // force sign or space
    00261                  field_flags |= FLAG_SIGN_SPACE;
    00262                  break;
    00263              case '0':
    00264                  // pad with leading 0
    00265                  field_flags |= FLAG_LEAD_ZERO;
    00266                  break;
    00267              default:
    00268                  ASSERT_ERR(0);
    00269                  break;
    00270              }
    00271              break;
    00272
    00273          case S_WIDTH:
    00274              if (c != '*')
    00275              {
    00276                  // add digit to current field width
    00277                  field_width = field_width * 10 + (c - '0');
    00278              }
    00279              else
    00280              {
    00281                  field_width = (int)va_arg(args, int);
    00282              }
    00283              break;
    00284
    00285          case S_DOT:
    00286              // Clear the field_precision variable
    00287              field_precision = 0;
    00288              break;
    00289
    00290          case S_PRECIS:
    00291              if (c != '*')
    00292              {
    00293                  // Add digit to field_precision variable
    00294                  field_precision = field_precision * 10 + (c - '0');
    00295              }
    00296              else
    00297              {
    00298                  field_precision = (int)va_arg(args, int);
    00299              }
    00300              break;
    00301
    00302          case S_SIZE:
    00303              // currently ignored
    00304              switch (c)
    00305              {
    00306              case 'l':
    00307                  // 'l' => long int
    00308                  field_flags |= FLAG_LONG;
    00309                  break;
    00310
    00311              #ifdef FLAG_SHORT_SUPPORTED
    00312              case 'h':
    00313                  // 'h' => short int
    00314                  field_flags |= FLAG_SHORT;
    00315                  break;
    00316              #endif // FLAG_SHORT_SUPPORTED
    00317
    00318              default:
    00319                  ASSERT_ERR(0);
    00320                  break;
    00321              }
    00322              break;
    00323
    00324          case S_TYPE:
    00325
    00326              // Now the options have been decoded
    00327              switch (c)
    00328              {
    00329                  // c
    00330                  case 'c':
    00331                      // Store byte in Tx buffer
    00332                      buffer_tmp[0] = (char)va_arg(args, int);
    00333                      fmt_field_ptr = buffer_tmp;
    00334                      fmt_field_size = 1;
    00335                      break;
    00336
    00337
    00338                  // String
    00339                  case 's':
    00340                      // Read parameter (pointer on string)
    00341                      fmt_field_ptr =  va_arg(args, char *);
    00342                      fmt_field_size = 0;
    00343                      if (fmt_field_ptr != NULL)
    00344                      {
    00345                          // Compute the length of the string
    00346                          // field_precision is the maximum number of character to be display
    00347                          tmp_ptr =  fmt_field_ptr;
    00348                          while (*tmp_ptr != '\0')
    00349                          {
    00350                              if (field_precision == 0)
    00351                                  break;
    00352                              if (field_precision > 0)
    00353                                  field_precision --;
    00354                              tmp_ptr++;
    00355                              fmt_field_size++;
    00356                          }
    00357                      }
    00358                      break;
    00359
    00360                  // MAC address
    00361                  case 'm':
    00362                  case 'M':
    00363                      {
    00364                      int i;
    00365                      fmt_field_ptr   = buffer_tmp;
    00366                      tmp_ptr         = va_arg(args, char *);
    00367                      fmt_field_size  = 17;
    00368                      for(i = 5;;)
    00369                      {
    00370                          value = (unsigned char) *tmp_ptr++;
    00371                          *fmt_field_ptr++ = hex_upper_table[value >> 4];
    00372                          *fmt_field_ptr++ = hex_upper_table[value & 0xF];
    00373                          if (i-- == 0) break;
    00374                          *fmt_field_ptr++ = ':';
    00375                      }
    00376                      fmt_field_ptr = buffer_tmp;
    00377                      break;
    00378                      }
    00379
    00380                  case 'a':
    00381                  case 'A':
    00382                      fmt_field_ptr = buffer_tmp;
    00383                      tmp_ptr = va_arg(args, char *);
    00384                      // prevent overflow
    00385                      field_width = co_min(field_width, sizeof(buffer_tmp)/3);
    00386                      // if no width given
    00387                      if (!field_width) field_width = 16;
    00388                      fmt_field_size = field_width * 3 - 1 ;
    00389                      for(;;)
    00390                      {
    00391                          value = (unsigned char) *tmp_ptr++;
    00392                          *fmt_field_ptr++ = hex_upper_table[value >> 4];
    00393                          *fmt_field_ptr++ = hex_upper_table[value & 0xF];
    00394                          if (--field_width == 0) break;
    00395                          // sep . (or : on align)
    00396                          if (3 & (uint32_t) tmp_ptr) *fmt_field_ptr++ = '.';
    00397                          else *fmt_field_ptr++ = ':';
    00398                      }
    00399                      fmt_field_ptr = buffer_tmp;
    00400                      break;
    00401
    00402                  case 'i':   // signed decimal
    00403                      c = 'd';
    00404                  case 'd':   // signed decimal
    00405                  case 'u':   // unsigned
    00406                  case 'X':   // hexa
    00407                  case 'x':   // hexa
    00408                  case 'b':   // binary
    00409
    00410                      // Point to the last byte of the buffer (go backward during conversion)
    00411                      fmt_field_ptr = buffer_tmp + sizeof(buffer_tmp);
    00412                      fmt_field_size = 0;
    00413
    00414                      // Get the value
    00415                      if (field_flags & FLAG_LONG)
    00416                      {
    00417                          // long
    00418                          value = va_arg(args, uint32_t);
    00419                      }
    00420                      #ifdef FLAG_SHORT_SUPPORTED
    00421                      else if(field_flags & FLAG_SHORT)
    00422                      {
    00423                          if (c == 'd')
    00424                          {
    00425                              // extend the sign
    00426                              value = (int16_t) va_arg(args, int);
    00427                          }
    00428                          else
    00429                          {
    00430                              value = (uint16_t) va_arg(args, int);
    00431                          }
    00432                      }
    00433                      #endif // FLAG_SHORT_SUPPORTED
    00434                      else
    00435                      {
    00436                          // int
    00437                          // extend the sign
    00438                          value = va_arg(args, int);
    00439                      }
    00440
    00441                      switch (c)
    00442                      {
    00443                      case 'd':
    00444                              // Separate the sign to display it before the number
    00445                              if (value < 0)
    00446                              {
    00447                                  value =  (uint32_t)(-value);
    00448                                  // remember negative sign
    00449                                  field_flags |= FLAG_NEGATIVE;
    00450                              }
    00451
    00452                      case 'u':
    00453                              do
    00454                              {
    00455                                  // go backward
    00456                                  fmt_field_ptr--;
    00457                                  *fmt_field_ptr = ('0'+ ((char) (value % 10)));
    00458                                  value = value / 10;
    00459                                  fmt_field_size++;
    00460                              }
    00461                              while (value != 0);
    00462
    00463                              // Add the sign
    00464                              if (field_flags & FLAG_NEGATIVE)
    00465                              {   // prefix with a '-'
    00466                                  // go backward
    00467                                  fmt_field_ptr--;
    00468
    00469                                  *fmt_field_ptr = '-';
    00470                                  fmt_field_size++;
    00471                              }
    00472                              else if (field_flags & FLAG_SIGN)
    00473                              {   // prefix with a '+' (sign is forced)
    00474                                  // go backward
    00475                                  fmt_field_ptr--;
    00476                                  *fmt_field_ptr = '+';
    00477                                  fmt_field_size++;
    00478                              }
    00479                              else if (field_flags & FLAG_SIGN_SPACE)
    00480                              {   // prefix with a ' ' (used instead of '+')
    00481                                  // go backward
    00482                                  fmt_field_ptr--;
    00483                                  *fmt_field_ptr = ' ';
    00484                                  fmt_field_size++;
    00485                              }
    00486                              break;
    00487
    00488                      case 'x':
    00489                          #ifdef SUPPORT_LOWER_CASE_HEX
    00490                              do
    00491                              {
    00492                                  // go backward
    00493                                  fmt_field_ptr--;
    00494                                  *fmt_field_ptr = hex_lower_table[value & 0XFUL];
    00495                                  value = ((uint32_t) value) >> 4;
    00496                                  fmt_field_size++;
    00497                              }
    00498                              while (value != 0);
    00499                              break;
    00500                          #endif
    00501
    00502                      case 'X':
    00503                              do
    00504                              {
    00505                                  // go backward
    00506                                  fmt_field_ptr--;
    00507                                  *fmt_field_ptr = hex_upper_table[value & 0XFUL];
    00508                                  value = ((uint32_t) value) >> 4;
    00509                                  fmt_field_size++;
    00510                              }
    00511                              while (value != 0);
    00512                              break;
    00513
    00514                      case 'b':
    00515                              do
    00516                              {
    00517                                  // go backward
    00518                                  fmt_field_ptr--;
    00519                                  *fmt_field_ptr = '0' + ((char) (value & 0x01UL));
    00520                                  value = ((uint32_t) value) >> 1;
    00521                                  fmt_field_size++;
    00522                              }
    00523                              while (value != 0);
    00524                              break;
    00525                      default:
    00526                          //ASSERT_ERR(0);
    00527                          break;
    00528                      } // embedded switch type
    00529
    00530                      default:
    00531                          //ASSERT_ERR(0);
    00532                          break;
    00533              } // switch type
    00534
    00535
    00536              // Add padding
    00537              field_padding = field_width - fmt_field_size;
    00538
    00539              // put out the padding, prefix, and text, in the correct order
    00540              if (field_flags & FLAG_LEAD_ZERO)
    00541              {
    00542                  // Add leading zeros
    00543                  while (field_padding > 0)
    00544                  {
    00545                      WRITE_CHAR('0');
    00546                      field_padding--;
    00547                  }
    00548              }
    00549              else if (!(field_flags & FLAG_LEFT))
    00550              {
    00551                  while (field_padding > 0)
    00552                  {
    00553                      WRITE_CHAR(' ');
    00554                      field_padding--;
    00555                  }
    00556              }
    00557
    00558              // Copy the formated field
    00559              while (fmt_field_size > 0)
    00560              {
    00561                  WRITE_CHAR(*fmt_field_ptr);
    00562                  fmt_field_ptr++;
    00563                  fmt_field_size--;
    00564              }
    00565
    00566              // Add blanks at the rigth (means (field_flags & FLAG_LEFT))
    00567              while ((field_padding > 0))
    00568              {
    00569                  WRITE_CHAR(' ');
    00570                  field_padding--;
    00571              }
    00572              break;
    00573
    00574          default:
    00575              ASSERT_ERR(0);
    00576          } // switch state
    00577      } // while
    00578
    00579      #undef WRITE_CHAR
    00580
    00581      if (remain)
    00582      {
    00583          *buffer = '\0';
    00584      }
    00585      else if (size)
    00586      {
    00587          buffer[-1] = '\0';
    00588      }
    00589
    00590      return res;
    00591 }
    00592
    00593 #if NX_PRINT == NX_PRINT_IPC
    00594
    00604 static void dbg_emb_vprintf(bool force, const char *fmt_usr, va_list args)
    00605 {
    00606     int mutex;
    00607     GLOBAL_INT_DISABLE();
    00608     mutex = dbg_env.print_mutex;
    00609     mutex++;
    00610     dbg_env.print_mutex = mutex;
    00611     GLOBAL_INT_RESTORE();
    00612
    00613     if (mutex == 1)
    00614     {
    00615         unsigned int len = dbg_vsnprintf(dbg_env.print_buffer, sizeof(dbg_env.print_buffer),
    00616                                          fmt_usr, args);
    00617
    00618         if (len < sizeof(dbg_env.print_buffer))
    00619             len ++;
    00620         else
    00621             len = sizeof(dbg_env.print_buffer);
    00622
    00623         ipc_emb_print_fwd(force, len, dbg_env.print_buffer);
    00624
    00625         // If an IRQ print occurs between the test and the mutex clear after the
    00626         // loop, this print not will be notified! (no easy way to resolve this)
    00627         while (mutex != dbg_env.print_mutex)
    00628         {
    00629             mutex = dbg_env.print_mutex;
    00630
    00631             // print 'irq print occured ' mutex - 1 'times'
    00632         }
    00633         dbg_env.print_mutex = 0;
    00634     }
    00635 }
    00636 #endif
    00637
    00638
    00647 void dbg_test_print(const char *fmt, ...)
    00648 {
    00649     const char *fmt_usr = (const char*) fmt;
    00650     uint32_t severity = 0;
    00651
    00652     //printf ("%d %d %d %d\n", fmt_usr[0], fmt_usr[1], DBG_MOD_MAX, DBG_SEV_MIN);
    00653
    00654     if (dbg_env.filter_severity == 0) return;
    00655
    00656     do
    00657     {
    00658         // Get the prefix
    00659         unsigned char prefix = ((unsigned char)*fmt_usr) & 0xFF;
    00660
    00661         // ASCII char, start of the user string
    00662         if (prefix < DBG_MOD_MIN) break;
    00663
    00664         if (prefix < DBG_MOD_MAX)
    00665         {
    00666             // test module, if filtered returns
    00667             if (~dbg_env.filter_module & CO_BIT(prefix - DBG_MOD_MIN)) return;
    00668         }
    00669         else
    00670         {
    00671             // must be severity code
    00672             ASSERT_ERR(DBG_SEV_MIN <= prefix && prefix < DBG_SEV_MAX);
    00673             severity = (uint32_t)(prefix - DBG_SEV_MIN);
    00674
    00675             // test severity, if filtered returns
    00676             if (dbg_env.filter_severity <= severity) return;
    00677         }
    00678
    00679         // Check first and second char
    00680         fmt_usr++;
    00681     }
    00682     while (fmt_usr != fmt + 2);
    00683
    00684     // print
    00685     va_list args;
    00686     va_start(args, fmt);
    00687
    00688     #if NX_PRINT == NX_PRINT_IPC
    00689     dbg_emb_vprintf(severity<=DBG_SEV_IDX_ERR, fmt_usr, args);
    00690
    00691     #elif NX_PRINT == NX_PRINT_PRINTK
    00692     vprintk(fmt_usr, args);
    00693
    00694     #elif NX_PRINT == NX_PRINT_PRINTF
    00695     vprintf(fmt_usr, args);
    00696
    00697     #endif
    00698
    00699     va_end(args);
    00700 }
    00701
    00718 uint32_t dbg_snprintf(char *buffer, uint32_t size, const char *fmt, ...)
    00719 {
    00720     uint32_t ret;
    00721     const char *fmt_usr = (const char*) fmt;
    00722
    00723     // print
    00724     va_list args;
    00725     va_start(args, fmt);
    00726
    00727     ret = dbg_vsnprintf(buffer, size, fmt_usr, args);
    00728
    00729     va_end(args);
    00730
    00731     return ret;
    00732 }
    00733