summaryrefslogtreecommitdiffstats
path: root/source/ct-Bot/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/ct-Bot/log.c')
-rw-r--r--source/ct-Bot/log.c290
1 files changed, 290 insertions, 0 deletions
diff --git a/source/ct-Bot/log.c b/source/ct-Bot/log.c
new file mode 100644
index 0000000..202a7d2
--- /dev/null
+++ b/source/ct-Bot/log.c
@@ -0,0 +1,290 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ */
+
+/*! @file log.c
+ * @brief Routinen zum Loggen von Informationen. Es sollten ausschliesslich nur
+ * die Log-Makros: LOG_DEBUG(), LOG_INFO(), LOG_WARN(), LOG_ERROR() und LOG_FATAL()
+ * verwendet werden.
+ * Eine Ausgabe kann wie folgt erzeugt werden:
+ * LOG_DEBUG(("Hallo Welt!"));
+ * LOG_INFO(("Wert x=%d", x));
+ * Wichtig ist die doppelte Klammerung. Bei den Ausgaben kann auf ein Line Feed
+ * '\n' am Ende des Strings verzichtet werden, da dies automatisch angeh�ngt
+ * hinzugefuegt wird.
+ *
+ * @author Andreas Merkle (mail@blue-andi.de)
+ * @date 27.02.06
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "log.h"
+#include "display.h"
+#include "command.h"
+#include "uart.h"
+
+#ifdef LOG_AVAILABLE
+
+#ifdef PC
+#include <pthread.h>
+#endif /* PC */
+
+#ifdef LOG_DISPLAY_AVAILABLE
+ /*! Nummer des Screens auf den Loggings ausgegeben werden sollen. */
+ #define LOG_TO_SCREEN 4
+
+ /*! Groesse des Puffers fuer die Logausgaben bei Verwendung des LCD-Displays. */
+ #define LOG_BUFFER_SIZE (DISPLAY_LENGTH + 1)
+#else
+ /*! Groesse des Puffers fuer die Logausgaben ueber UART und ueber TCP/IP. */
+ #define LOG_BUFFER_SIZE 200
+#endif /* LOG_DISPLAY_AVAILABLE */
+
+
+#ifdef PC
+ /*! Schuetzt den Ausgabepuffer */
+ #define LOCK() pthread_mutex_lock(&log_buffer_mutex);
+ /*! Hebt den Schutz fuer den Ausgabepuffer wieder auf */
+ #define UNLOCK() pthread_mutex_unlock(&log_buffer_mutex);
+#else
+ /*! Schuetzt den Ausgabepuffer */
+ #define LOCK() /* TODO */
+ /*! Hebt den Schutz fuer den Ausgabepuffer wieder auf */
+ #define UNLOCK() /* TODO */
+#endif /* PC */
+
+/*!
+ * Liefert den Log-Typ als String.
+ * @param log_type Log-Typ
+ * @return char*
+ */
+static char* log_get_type_str(LOG_TYPE log_type);
+
+/*! Puffer fuer das Zusammenstellen einer Logausgabe */
+static char log_buffer[LOG_BUFFER_SIZE];
+
+#ifdef PC
+ /*! Schuetzt den Ausgabepuffer */
+ static pthread_mutex_t log_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif /* PC */
+
+#ifdef LOG_DISPLAY_AVAILABLE
+ /*! Zeile in der die naechste Logausgabe erfolgt. */
+ static uint16 log_line = 0;
+#endif /* LOG_DISPLAY_AVAILABLE */
+
+/*!
+ * Schreibt Angaben ueber Datei, Zeilennummer und den Log-Typ in den Puffer.
+ * Achtung, Mutex wird gelockt und muss explizit durch log_end() wieder
+ * freigegeben werden!
+ * @param filename Dateiname
+ * @param line Zeilennummer
+ * @param log_type Log-Typ
+ */
+extern void log_begin(char *filename, unsigned int line, LOG_TYPE log_type) {
+
+/* Ausgaben ueber das LCD-Display werden ohne Dateiname und Zeilennumer
+ * gemacht. Der Log-Typ versteckt sich im ersten Buchstaben. Durch eine
+ * die Markierung mit '>' erkennt man das letzte Logging.
+ * Nur bei Ausgaben ueber UART und an ct-Sim werden Dateiname, Zeilennummer
+ * und der Log-Typ vollstaendig ausgegeben.
+ */
+ #ifdef LOG_DISPLAY_AVAILABLE
+
+ LOCK();
+
+ /* Nur auf einem bestimmten Screen werden Loggings ausgegeben. */
+ if (display_screen != LOG_TO_SCREEN) {
+ log_buffer[0] = '\0';
+ return;
+ }
+
+ /* Zum ersten Mal aufgerufen? */
+ if (log_line == 0) {
+ log_line++;
+ } else {
+ /* Alte Markierung loeschen */
+ if (log_line - 1 == 0) {
+ display_cursor(4, 1);
+ }
+ else {
+ display_cursor(log_line - 1, 1);
+ }
+ display_printf(" ");
+ }
+ display_cursor(log_line, 1);
+ log_line++;
+ if (log_line >= DISPLAY_SCREENS) {
+ log_line = 1;
+ }
+
+ snprintf(log_buffer, LOG_BUFFER_SIZE, ">%s:", log_get_type_str(log_type));
+
+ #else
+
+ char *ptr = NULL;
+
+ /* Nur den Dateinamen loggen, ohne Verzeichnisangabe */
+ ptr = strrchr(filename, '/');
+
+ if (ptr == NULL)
+ ptr = filename;
+ else
+ ptr++;
+
+ LOCK();
+
+ snprintf(log_buffer, LOG_BUFFER_SIZE, "%s(%d)\t%s\t",
+ ptr, line, log_get_type_str(log_type));
+
+ #endif
+
+ return;
+}
+
+/*!
+ * Schreibt die eigentliche Ausgabeinformation in den Puffer.
+ * @param format Format
+ */
+extern void log_printf(char *format, ...) {
+
+ va_list args;
+ unsigned int len = strlen(log_buffer);
+
+ #ifdef LOG_DISPLAY_AVAILABLE
+ /* Nur auf einem bestimmten Screen werden Loggings ausgegeben. */
+ if (display_screen != LOG_TO_SCREEN)
+ return;
+ #endif
+
+ va_start(args, format);
+ vsnprintf(&log_buffer[len], LOG_BUFFER_SIZE - len, format, args);
+ va_end(args);
+
+ return;
+}
+
+/*!
+ * Gibt den Puffer entsprechend aus.
+ */
+extern void log_end(void) {
+
+ #ifdef LOG_UART_AVAILABLE
+ /* String ueber UART senden, ohne '\0'-Terminierung */
+ uart_write((uint8*)log_buffer, strlen(log_buffer));
+ /* Line feed senden */
+ uart_write((uint8*)LINE_FEED,strlen(LINE_FEED));
+ #endif /* LOG_UART_AVAILABLE */
+
+ #ifdef LOG_CTSIM_AVAILABLE
+ /* Kommando an ct-Sim senden, ohne Line feed am Ende. */
+ command_write_data(CMD_LOG, SUB_CMD_NORM, NULL, NULL, log_buffer);
+ #endif /* LOG_CTSIM_AVAILABLE */
+
+ #ifdef LOG_DISPLAY_AVAILABLE
+ /* Nur auf einem bestimmten Screen werden Loggings ausgegeben. */
+ if (display_screen == LOG_TO_SCREEN) {
+ /* String aufs LCD-Display schreiben */
+ display_printf("%s", log_buffer);
+ }
+ #endif /* LOG_DISPLAY_AVAILABLE */
+
+ /* Wenn das Logging aktiviert und keine Ausgabeschnittstelle
+ * definiert ist, dann wird auf dem PC auf die Konsole geschrieben.
+ */
+
+ #ifdef LOG_STDOUT_AVAILABLE
+ printf("%s\n", log_buffer);
+ #endif /* LOG_STDOUT_AVAILABLE */
+
+ UNLOCK();
+
+ return;
+}
+
+#ifdef LOG_DISPLAY_AVAILABLE
+
+/*!
+ * Liefert den Log-Typ als String.
+ * @param log_type Log-Typ
+ * @return char*
+ */
+static char* log_get_type_str(LOG_TYPE log_type) {
+
+ switch(log_type) {
+ case LOG_TYPE_DEBUG:
+ return "D";
+
+ case LOG_TYPE_INFO:
+ return "I";
+
+ case LOG_TYPE_WARN:
+ return "W";
+
+ case LOG_TYPE_ERROR:
+ return "E";
+
+ case LOG_TYPE_FATAL:
+ return "F";
+
+ default:
+ break;
+ }
+
+ return "";
+}
+
+#else
+
+/*!
+ * Liefert den Log-Typ als String.
+ * @param log_type Log-Typ
+ * @return char*
+ */
+static char* log_get_type_str(LOG_TYPE log_type) {
+
+ switch(log_type) {
+ case LOG_TYPE_DEBUG:
+ return "- DEBUG -";
+
+ case LOG_TYPE_INFO:
+ return "- INFO -";
+
+ case LOG_TYPE_WARN:
+ return "- WARNING -";
+
+ case LOG_TYPE_ERROR:
+ return "- ERROR -";
+
+ case LOG_TYPE_FATAL:
+ return "- FATAL -";
+
+ default:
+ break;
+ }
+
+ return "";
+}
+
+#endif /* LOG_DISPLAY_AVAILABLE */
+
+#endif /* LOG_AVAILABLE */