home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / log.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  11.4 KB  |  618 lines

  1.  
  2. /*
  3.  *    Logging routines
  4.  */
  5.  
  6. #include <stdarg.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9.  
  10. #define __LOG__
  11.  
  12. #include "v9t9_common.h"
  13. #include "system.h"
  14. #include "v9t9.h"
  15. #include "command.h"
  16. #include "debugger.h"
  17. #include "dsr.h"
  18. #include "log.h"
  19.  
  20. //  Mask for currently logged sources (see log.h)
  21. //static u32  logsrc = 0;
  22.  
  23. //  Verbosity level (0=minimum, ...)
  24. static int  loglevel[32];
  25.  
  26. //  Verbosity echoed to screen
  27. //static int  consoleverbosity[32];
  28.  
  29. //  Error buffer
  30. static char strbuf[1024];
  31. static int  stridx;
  32.  
  33. static void
  34. lstart(void)
  35. {
  36.     stridx = 0;
  37. }
  38.  
  39. static void
  40. lend(u32 srcflags)
  41. {
  42.     strbuf[stridx] = 0;
  43.     system_log(srcflags, strbuf);
  44. }
  45.  
  46.  
  47. static void
  48. vlprintf(const char *format, va_list va)
  49. {
  50.     int         len;
  51.  
  52.     len = vsnprintf(strbuf + stridx, sizeof(strbuf) - stridx, format, va);
  53.  
  54.     // old usage
  55.     if (len < 0)
  56.         len = sizeof(strbuf) - stridx - 1;
  57.     else if (len > sizeof(strbuf) - stridx)
  58.         len = sizeof(strbuf) - stridx - 1;
  59.  
  60.     stridx += len;
  61. }
  62.  
  63. static void
  64. lprintf(const char *format, ...)
  65. {
  66.     va_list     va;
  67.  
  68.     va_start(va, format);
  69.     vlprintf(format, va);
  70.     va_end(va);
  71. }
  72.  
  73. ///////////////////////////////////
  74.  
  75. static      u32
  76. lookup_system_name(char *name)
  77. {
  78.     int         idx;
  79.  
  80.     if (strcasecmp(name, "all") == 0)
  81.         return ~0;
  82.     for (idx = 0; idx < sizeof(log_src) / sizeof(char *); idx++) {
  83.         if (strcasecmp(name, log_src[idx]) == 0)
  84.             return 1 << idx;
  85.     }
  86.     return 0;
  87. }
  88.  
  89. static
  90. DECL_SYMBOL_ACTION(command_toggle_logging)
  91. {
  92.     int         level;
  93.     char       *name;
  94.     u32         mask, bit;
  95.     int            idx;
  96.  
  97.     if (task == csa_READ)
  98.     {
  99.         if (iter >= sizeof(log_src) / sizeof(log_src[0]))
  100.             return 0;
  101.         command_arg_set_string(SYM_ARG_1st, log_src[iter]);
  102.         command_arg_set_num(SYM_ARG_2nd, loglevel[iter]);
  103.         return 1;
  104.     }
  105.     
  106.     command_arg_get_string(SYM_ARG_1st, &name);
  107.     command_arg_get_num(SYM_ARG_2nd, &level);
  108.  
  109.     if ((mask = lookup_system_name(name)) == 0) {
  110.         logger(LOG_ERROR | LOG_USER, "Unknown subsystem '%s'\n", name);
  111.         return 0;
  112.     }
  113.  
  114.     for (idx = 0, bit = 1; 
  115.          idx < LOG_NUM_SRC; 
  116.          idx ++, bit += bit) {
  117.         if (mask & bit) {
  118.             loglevel[idx] = level;
  119.         }
  120.     }
  121.  
  122.     return 1;
  123. }
  124.  
  125. static
  126. DECL_SYMBOL_ACTION(command_list_log_systems)
  127. {
  128.     int         idx;
  129.  
  130.     logger(LOG_USER, "Supported logging subsystems:");
  131.     for (idx = 0; idx < sizeof(log_src) / sizeof(char *); idx++) {
  132.         logger(LOG_USER, "\t%20s\t(level=%d)", 
  133.                log_src[idx], loglevel[idx]);
  134.     }
  135.     logger(LOG_USER, "\n");
  136.     return 1;
  137. }
  138.  
  139. /*
  140. static
  141. DECL_SYMBOL_ACTION(command_log_verbosity)
  142. {
  143.     int         delta;
  144.  
  145.     if (task == csa_READ)
  146.     {
  147.         if (!iter)
  148.         {
  149.             command_arg_set_num(sym->args, logverbosity);
  150.             return 1;
  151.         }
  152.         return 0;
  153.     }
  154.     command_arg_get_num(sym->args, &delta);
  155.     log_verbose(delta);
  156.     return 1;
  157. }
  158.  
  159. static
  160. DECL_SYMBOL_ACTION(command_log_visible_verbosity)
  161. {
  162.     int         delta;
  163.  
  164.     if (task == csa_READ)
  165.     {
  166.         if (!iter)
  167.         {
  168.             command_arg_set_num(sym->args, logvisibleverbosity);
  169.             return 1;
  170.         }
  171.         return 0;
  172.     }
  173.     command_arg_get_num(sym->args, &delta);
  174.     log_visible_verbose(delta);
  175.     return 1;
  176. }
  177. */
  178.  
  179. void
  180. log_add_commands(void)
  181. {
  182.     command_symbol_table *logs = command_symbol_table_new("Logging Commands",
  183.                                                           "These options control sources and verbosity of logging",
  184.  
  185.       command_symbol_new
  186.       ("Log",
  187.        "Toggle logging for given subsystem",
  188.        c_DYNAMIC,
  189.        command_toggle_logging  /* action */ ,
  190.        RET_FIRST_ARG           /* ret */ ,
  191.         command_arg_new_string
  192.         ("system",
  193.          "one of the subsystems from ListLogSystems",
  194.          NULL,
  195.          NEW_ARG_STR(10),
  196.        command_arg_new_num
  197.        ("log level",
  198.         "level of verbosity (0=off...9=max); "
  199.         "a negative value sends output only to file, else output "
  200.         "is copied to console or log window",
  201.         NULL,
  202.         NEW_ARG_NUM(int),
  203.         NULL /* next */)),
  204.  
  205.        command_symbol_new
  206.        ("ListLogSystems",
  207.         "List targets for logging",
  208.         c_DONT_SAVE,
  209.         command_list_log_systems    /* action */ ,
  210.         NULL /* ret */ ,
  211.         NULL,
  212.  
  213. #if 0
  214.         command_symbol_new
  215.         ("LogVerbosity",
  216.          "Change logging verbosity for log file",
  217.          c_DYNAMIC,
  218.          command_log_verbosity         /* action */ ,
  219.          RET_FIRST_ARG                /* ret */ ,
  220.          command_arg_new_num
  221.          ("delta",
  222.           "delta>0 increases verbosity, delta<0 decreases verbosity",
  223.           NULL,
  224.           NEW_ARG_NUM(u8),
  225.           NULL    /* next */
  226.          ),
  227.  
  228.          command_symbol_new
  229.          ("ConsoleLogVerbosity",
  230.           "Change logging verbosity for messages echoed to console; "
  231.           "note:  LogVerbosity is treated as being at least ConsoleLogVerbosity, "
  232.           "so messages will always be logged to disk",
  233.           c_DYNAMIC,
  234.           command_log_visible_verbosity    /* action */ ,
  235.           RET_FIRST_ARG                    /* ret */ ,
  236.           command_arg_new_num
  237.           ("delta",
  238.            "delta>0 increases verbosity, delta<0 decreases verbosity",
  239.            NULL,
  240.            NEW_ARG_NUM
  241.            (u8),
  242.            NULL    /* next */
  243.           ),
  244. #endif
  245.           NULL    /* next */
  246.          )),
  247.  
  248.       NULL /* sub */ ,
  249.  
  250.       NULL    /* next */
  251.     );
  252.  
  253.     command_symbol_table_add_subtable(universe, logs);
  254.  
  255. }
  256.  
  257. //  Initialize log
  258. void
  259. initlog(void)
  260. {
  261.     memset(loglevel, 0, sizeof(loglevel));
  262. //    system_initlog();
  263. }
  264.  
  265. //  Terminate log
  266. void
  267. termlog(void)
  268. {
  269. //    system_termlog();
  270. }
  271.  
  272. static int log_2(u32 mask)
  273. {
  274.     int idx = 0;
  275.     u32 bit = 1;
  276.     while (idx < LOG_NUM_SRC && !(mask & bit)) {
  277.         idx++;
  278.         bit <<=1;
  279.     }
  280.     return idx;
  281. }
  282.  
  283. #define log_abs(x) ((x) < 0 ? -(x) : (x))
  284.  
  285. int
  286. log_level(int src)
  287. {
  288.     return log_abs(loglevel[src]);
  289. }
  290.  
  291. const char *
  292. log_name(int src)
  293. {
  294.     if (src >= LOG_GENERAL && src < LOG_NUM_SRC)
  295.         if (*log_src[src])
  296.             return log_src[src];
  297.         else
  298.             return "General";
  299.     else
  300.         return 0L;
  301. }
  302.  
  303. bool
  304. log_enabled(int srcflags)
  305. {
  306.     int         verb = (srcflags & LOG_VERBOSE_MASK) >> LOG_VERBOSE_SHIFT;
  307.     int            srcidx = (srcflags & LOG_SRC_MASK);
  308.  
  309.     // LOG_USER or LOG_FATAL forces output
  310.     if (!LOG_IS_VISIBLE(srcflags)) {
  311.         // verbosity?
  312.         if (verb > log_abs(loglevel[srcidx]))
  313.             return false;
  314.     }
  315.     return true;
  316. }
  317.  
  318. //    Return source flags coerced to add LOG_USER if necessary
  319. int
  320. log_coerced_to_user(int srcflags)
  321. {
  322.     int         verb = (srcflags & LOG_VERBOSE_MASK) >> LOG_VERBOSE_SHIFT;
  323.     int            srcidx = (srcflags & LOG_SRC_MASK);
  324.  
  325.     return srcflags | (verb < loglevel[srcidx] ? LOG_USER : 0);
  326. }
  327.  
  328.  
  329. //  Log something.  srcflags=LOG_xxx
  330. void
  331. vlogger(u32 srcflags, const char *format, va_list va)
  332. {
  333.     static u32    lastsrc = 0;
  334.  
  335.     if (!log_enabled(srcflags)) 
  336.         return;
  337.  
  338.     // start new buffer
  339.     lstart();
  340.  
  341.     // start new line?
  342.     if (lastsrc != (srcflags & (LOG_SRC_MASK|LOG_TYPE_MASK)) &&
  343.         (srcflags & LOG_SRC_MASK)) {
  344.         lastsrc = srcflags & (LOG_SRC_MASK|LOG_TYPE_MASK);
  345. #if 0
  346.         lprintf("%-7s ", log_src[srcflags & LOG_SRC_MASK]);
  347.  
  348.         if ((srcflags & LOG_TYPE_MASK) == LOG_WARN)
  349.             lprintf("warn : ");
  350.         else if ((srcflags & LOG_TYPE_MASK) == LOG_ERROR)
  351.             lprintf("error: ");
  352.         else if ((srcflags & LOG_TYPE_MASK) == LOG_FATAL)
  353.             lprintf("fatal: ");
  354.         else if ((srcflags & LOG_TYPE_MASK) == LOG_DEBUG)
  355. #ifdef DEBUG
  356.             lprintf("debug: ");
  357. #else
  358.             return;
  359. #endif
  360.         else
  361.             lprintf(": ");
  362. #endif
  363.  
  364. #ifndef DEBUG
  365.         if ((srcflags & LOG_TYPE_MASK) == LOG_DEBUG)
  366.             return;
  367. #endif
  368.     }
  369.     // emit formatted text
  370.     vlprintf(format, va);
  371.  
  372.     // dump text
  373.     // if loglevel is positive, LOG_USER will always be set (else
  374.     // we would have exited above); if loglevel is negative,
  375.     // LOG_USER will never be set.
  376.     lend(log_coerced_to_user(srcflags));
  377.  
  378.     // die if it was fatal
  379.     if ((srcflags & LOG_TYPE_MASK) == LOG_FATAL) {
  380.         v9t9_term(1);
  381.         abort();
  382.     }
  383. }
  384.  
  385. void
  386. logger(u32 flags, const char *format, ...)
  387. {
  388.     va_list     va;
  389.  
  390.     va_start(va, format);
  391.     vlogger(flags, format, va);
  392.     va_end(va);
  393. }
  394.  
  395.  
  396. void
  397. OSerror(int err, char *format, ...)
  398. {
  399.     va_list     ap;
  400.  
  401.     va_start(ap, format);
  402.  
  403.     lstart();
  404.     lprintf("\nOS error:\t");
  405.     vlprintf(format, ap);
  406.     lprintf("%s (error %d)\n", OS_GetErrText(err), err);
  407.     lend(LOG_USER);
  408.     va_end(ap);
  409. }
  410.  
  411. //    Print a status item for frontend
  412. void
  413. report_status(status_item item, ...)
  414. {
  415.     va_list va;
  416.     va_start(va, item);
  417.     system_report_status(item, va);
  418.     va_end(va);
  419. }
  420.  
  421. //    Format status item into text, if verbosity allows it
  422. void
  423. report_status_text(status_item item, va_list va,
  424.                    char *buffer, int bufsz)
  425.  
  426. {
  427.     *buffer = 0;
  428.     if (bufsz < 32)    return;
  429.  
  430.     switch (item)
  431.     {
  432.     case STATUS_CYCLES_SECOND:
  433.     case STATUS_FRAMES_SECOND:
  434.         break;
  435.  
  436.     case STATUS_DISK_ACCESS:
  437.     {
  438.         int disk, onoff;
  439.         disk = va_arg(va, int);
  440.         onoff = va_arg(va, int);
  441.  
  442.         if (log_enabled((dsr_is_emu_disk(disk) ? LOG_EMUDISK : LOG_REALDISK) | L_1))
  443.             sprintf(buffer, "Disk %d %s\n",
  444.                     disk,
  445.                     onoff ? "on" : "off");
  446.         break;
  447.     }
  448.     case STATUS_RS232_ACCESS:
  449.     {
  450.         if (log_enabled(LOG_RS232 | L_1))
  451.             sprintf(buffer, "RS232/%d %s\n",
  452.                     va_arg(va, int),
  453.                     va_arg(va, int) ? "on" : "off");
  454.         break;
  455.     }
  456.  
  457.     case STATUS_DEBUG_REFRESH:
  458.         break;
  459.  
  460.     case STATUS_CPU_PC:
  461.         if (log_enabled(LOG_CPU | L_3))
  462.             sprintf(buffer, "[PC=>%04X] ",
  463.                 va_arg(va, int));
  464.         break;
  465.     case STATUS_CPU_STATUS:
  466.         if (log_enabled(LOG_CPU | L_3))
  467.             sprintf(buffer, "[ST=>%04X] ",
  468.                 va_arg(va, int));
  469.         break;
  470.     case STATUS_CPU_WP:
  471.         if (log_enabled(LOG_CPU | L_2))
  472.             sprintf(buffer, "[WP=>%04X] ",
  473.                 va_arg(va, int));
  474.         break;
  475.  
  476.     case STATUS_CPU_REGISTER_VIEW:
  477.     {
  478.         if (log_enabled(LOG_CPU | L_1)) 
  479.         {
  480.             int reg;
  481.             char *ptr = buffer;
  482.             u16 wp = va_arg(va, int);
  483.             u16 *regs = va_arg(va, u16 *);
  484.         
  485.             ptr += sprintf(ptr, "WP=>%04X\n", wp);
  486.             for (reg = 0; reg < 16; reg++) {
  487.                 if (ptr + 12 > buffer + bufsz) break;
  488.                 ptr += sprintf(ptr, "R%1X=%04X  ",
  489.                                reg, regs[reg]);
  490.                 if ((reg & 7) == 7) {
  491.                     ptr += sprintf(ptr, "\n");
  492.                 }
  493.             }
  494.             *ptr = 0;
  495.         }
  496.         break;
  497.     }
  498.  
  499.     case STATUS_CPU_REGISTER_READ:
  500.     {
  501.         if (log_enabled(LOG_CPU | L_2))
  502.         {
  503.             int reg, val;
  504.             reg = va_arg(va, int);
  505.             val = va_arg(va, int);
  506.             sprintf(buffer, "[Read R%d=>%04X] ", 
  507.                 reg, val);
  508.         }
  509.         break;
  510.     }
  511.  
  512.     case STATUS_CPU_REGISTER_WRITE:
  513.     {
  514.         if (log_enabled(LOG_CPU | L_2))
  515.         {
  516.             int reg, val;
  517.             reg = va_arg(va, int);
  518.             val = va_arg(va, int);
  519.             sprintf(buffer, "[Wrote R%d=>%04X] ", 
  520.                 reg, val);
  521.         }
  522.         break;
  523.     }
  524.  
  525.     case STATUS_CPU_INSTRUCTION:
  526.     {
  527.         if (log_enabled(LOG_CPU | L_1))
  528.         {
  529.             Instruction *inst;
  530.             char *hex, *disasm, *op1, *op2;
  531.             inst = va_arg(va, Instruction *);
  532.             hex = va_arg(va, char *);
  533.             disasm = va_arg(va, char *);
  534.             op1 = va_arg(va, char *);
  535.             op2 = va_arg(va, char *);
  536.         
  537.             snprintf(buffer, bufsz, "%-10s %-5s %-22s %s%s%s%s%s%s\n",
  538.                      hex, inst->name, disasm,
  539.                      op1 ? "[" : "", op1 ? op1 : "", op1 ? "]" : "",
  540.                      op2 ? " [" : "", op2 ? op2 : "", op2 ? "]" : "");
  541.         }
  542.         break;
  543.     }
  544.  
  545.     case STATUS_CPU_INSTRUCTION_LAST:
  546.     {
  547.         if (log_enabled(LOG_CPU | L_1))
  548.         {
  549.             Instruction *inst;
  550.             char tmp[32];
  551.             char *op1, *op2;
  552.         
  553.             inst = va_arg(va, Instruction *);
  554.             op1 = va_arg(va, char *);
  555.             op2 = va_arg(va, char *);
  556.         
  557.             if (inst) {
  558.                 sprintf(tmp, "%s%s%s%s%s%s",
  559.                         op1 ? "{" : "", op1 ? op1 : "", op1 ? "}" : "",
  560.                         op2 ? " {" : "", op2 ? op2 : "", op2 ? "}" : "");
  561.                 sprintf(buffer, "%-16s", tmp);
  562.             } else {
  563.                 sprintf(buffer, "%-16s", "");
  564.             }
  565.         }
  566.         break;
  567.     }
  568.  
  569.     case STATUS_MEMORY_VIEW:
  570.     {
  571.         if (log_enabled(LOG_MEMORY | L_1))
  572.         {
  573.             Memory *s = va_arg(va, Memory *);
  574.             char *start, *end, *astart, *aend;
  575.  
  576.             debugger_hex_dump_line(s, 0, debugger_memory_view_size[s->which],
  577.                                    '=', ' ', ' ', '\n',
  578.                                    buffer, bufsz,
  579.                                    &start, &end,
  580.                                    &astart, &aend);
  581.             if (start) *(start-1) = '|';
  582.             if (end) *end = '|';
  583.         }
  584.         break;
  585.     }
  586.     case STATUS_MEMORY_READ:
  587.     {
  588.         if (log_enabled(LOG_MEMORY | L_2))
  589.         {
  590.             Memory *s = va_arg(va, Memory *);
  591.             sprintf(buffer, "[Read %d bytes at >%04X] ",
  592.                     s->len, s->addr);
  593.         }
  594.         break;
  595.     }
  596.     case STATUS_MEMORY_WRITE:
  597.     {
  598.         if (log_enabled(LOG_MEMORY | L_2))
  599.         {
  600.             Memory *s = va_arg(va, Memory *);
  601.             sprintf(buffer, "[Wrote %d bytes at >%04X] ",
  602.                     s->len, s->addr);
  603.         }
  604.         break;
  605.     }
  606.  
  607.     }
  608. }
  609.  
  610. void
  611. my_assert_func(char *file, int line, char *message)
  612. {
  613.     logger(LOG_FATAL | LOG_INTERNAL, "assertion failed:  %s:%d: %s\n",
  614.            file, line, message);
  615. }
  616.  
  617.  
  618.