Logo Search packages:      
Sourcecode: mas version File versions

mas_logging.c

/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
#include "mas_logging.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>

#define LOG_LEVELS      32
#define INDENT_AMOUNT   3

static int  current_log_level = -1; /* The current log level this is in */
static int  last_printed_level;     /* The last printed log level */
static char *log_levels[LOG_LEVELS];/* Pointers to the names of each log level */
static int  verbosity_level;  /* The verbosity level of messages to print */
static FILE *logfile;         /* The handle of the log file */
static int  entry_exit;       /* If true, all entries and exits from levels are printed */

/* Whitespace for quickly indenting messages. This is global so it can be initialized once. */
static char spaces[LOG_LEVELS * INDENT_AMOUNT]; 


/* Helper function that "indents" spaces[] */
static void indent(int level)
{
      static int  last_null = 0;


      /* Put a space on the last null character put in the string
       * and increase or decrease the amount of spaces before the 
       * first null. */
      spaces[last_null] = ' ';
      spaces[(level - 1) * INDENT_AMOUNT] = '\0';
      last_null = (level - 1) * INDENT_AMOUNT;
}


int masc_init_log_program(char *filename, char *first_log_title, int options)
{
      if(*filename == 0)
            logfile = stderr;
      else if((logfile = fopen(filename, "w")) == NULL)
            return -1;

      /* Turn off buffering so that all data is written to the disk immediately.
       * This makes sure all the data is written to the drive before a crash happens. */
      if(options & LINE_BUFFER)
            setvbuf(logfile, NULL, _IOLBF, 0);
      else if(options & NO_BUFFER)
            setvbuf(logfile, NULL, _IONBF, 0);

      /* Set this to print all the entry and exit levels. */
      if(options & PRINT_ENTRY_EXIT)
            entry_exit = 1;

      /* Fill spaces with whitespace. */
      memset(spaces, ' ', LOG_LEVELS * INDENT_AMOUNT);

      /* Set the first log title */
      current_log_level = 1;
      log_levels[0] = first_log_title;

      /* Print the logger is entering this level if entry_exit is set */
      if(entry_exit)
            fprintf(logfile, "1:(Entering) %s\n", first_log_title);

      return 1;
}

void masc_exit_log_program(void)
{
      /* Print the logger is entering this level if entry_exit is set */
      if(entry_exit)
            fprintf(logfile, "1:(Exiting) %s\n", log_levels[0]);

      fclose(logfile);
}

void masc_log_message(int verbosity, char *format, ...)
{
      int   i;
      va_list ap;

        if(current_log_level == -1) masc_init_log_program("", "", 0);

        /* Only print messages that are less then the current verbosity level. */
      if(verbosity > verbosity_level) return;

      if(!entry_exit)
      {
            /* If the current log level hasn't been printed into the file yet
             * print it. */
            if(current_log_level > last_printed_level)
                {
                  for(i = last_printed_level + 1; i <= current_log_level; i++)
                  {
                        indent(i);
                        fprintf(logfile, "%s%d: %s\n", spaces, i, log_levels[i - 1]);
                  }
                }
            else if(current_log_level < last_printed_level)
            {
                  indent(current_log_level);
                  fprintf(logfile, "%s%d: %s\n", spaces, current_log_level, log_levels[current_log_level - 1]);
            }
      }
      /* Print the message into the file */
        if ( format[0] == ' ' || format[0] == 9 )
        {
            indent(current_log_level);
            if ( spaces[0] != 0 ) fprintf(logfile, spaces);
            fprintf(logfile, "%d+ ", current_log_level);
        }
        else
        {
            indent(current_log_level+1);
            if ( spaces[0] != 0 ) fprintf(logfile, spaces);
        }

      va_start(ap, format);
      vfprintf(logfile, format, ap);
      va_end(ap);
      fprintf(logfile, "\n");

      /* Set the last printed level so that it is not printed out again */
      last_printed_level = current_log_level;
}

void masc_log_verbosity(int verbosity)
{
      verbosity_level = verbosity;
}

void masc_entering_log_level(char *log_title)
{
      if (current_log_level == -1) masc_init_log_program("", "", 0);

      current_log_level++;

      /* Set the pointer to the log title for this level */
      log_levels[current_log_level - 1] = log_title;

      /* Print the logger is entering this level if entry_exit is set */
      if(entry_exit)
      {
            indent(current_log_level);
            fprintf(logfile, "%s%d:(Entering) %s\n", spaces, current_log_level, log_levels[current_log_level - 1]);
      }
}

void masc_exiting_log_level(void)
{
      if (current_log_level == -1) masc_init_log_program("", "", 0);
    
      /* Make sure the level doesn't reach 0 or below */
      if(current_log_level <= 1)
            current_log_level = 1;
      else
            current_log_level--;

      if(last_printed_level > current_log_level) last_printed_level = current_log_level;

      /* Print the logger is exiting this level if entry_exit is set */
      if(entry_exit)
      {
            indent(current_log_level + 1);
            fprintf(logfile, "%s%d:(Exiting) %s\n", spaces, current_log_level + 1, log_levels[current_log_level]);
      }
}



Generated by  Doxygen 1.6.0   Back to index