Index: c/src/libmisc/monitor/README
===================================================================
--- c/src/libmisc/monitor/README	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
+++ c/src/libmisc/monitor/README	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
@@ -0,0 +1,7 @@
+#
+#  $Id$
+#
+
+This is a snapshot of a work in process.  It is the beginnings of a
+debug monitor task and trap handler which is tasking aware.
+
Index: c/src/libmisc/monitor/mon-monitor.c
===================================================================
--- c/src/libmisc/monitor/mon-monitor.c	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
+++ c/src/libmisc/monitor/mon-monitor.c	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
@@ -0,0 +1,307 @@
+/*
+ *	@(#)monitor.c	1.6 - 95/04/24
+ *	
+ */
+
+/*
+ *  mon-task.c
+ *
+ *  Description:
+ *	RTEMS monitor task
+ *	
+ *	
+ *	
+ *  TODO:
+ *	add pause command (monitor sleeps for 'n' ticks, then wakes up)
+ *      
+ */
+
+#include <rtems.h>
+/* #include <bsp.h> */
+
+#include "symbols.h"
+#include "monitor.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define STREQ(a,b)	(strcmp(a,b) == 0)
+
+/* set by trap handler */
+extern rtems_tcb       *debugger_interrupted_task;
+extern rtems_context   *debugger_interrupted_task_context;
+extern rtems_unsigned32 debugger_trap;
+
+/* our task id needs to be public so any debugger can resume us */
+rtems_unsigned32        rtems_monitor_task_id;
+
+
+rtems_symbol_table_t *rtems_monitor_symbols;
+
+
+#ifndef MONITOR_PROMPT
+#define MONITOR_PROMPT "rtems> "
+#endif
+
+#define MONITOR_WAKEUP_EVENT   RTEMS_EVENT_0
+
+/*
+ *  Function:	rtems_monitor_init
+ *
+ *  Description:
+ *	Create the RTEMS monitor task
+ *	
+ *  Parameters:
+ *	'monitor_suspend' arg is passed as initial arg to monitor task
+ *      If TRUE, monitor will suspend itself as it starts up.  Otherwise
+ *      it will begin its command loop.
+ *	
+ *  Returns:
+ *	
+ *	
+ *  Side Effects:
+ *	
+ *	
+ *  Notes:
+ *	
+ *	
+ *  Deficiencies/ToDo:
+ *	
+ *	
+ */
+
+/*
+ * make_argv(cp): token-count
+ *	Break up the command line in 'cp' into global argv[] and argc (return
+ *	value).
+ */
+
+int
+rtems_monitor_make_argv(
+    char *cp,
+    int  *argc_p,
+    char **argv)
+{
+    int argc = 0;
+
+    while ((cp = strtok(cp, " \t\n\r")))
+    {
+	argv[argc++] = cp;
+	cp = (char *) NULL;
+    }
+    argv[argc] = (char *) NULL;			/* end of argv */
+
+    return *argc_p = argc;
+}
+
+void
+rtems_monitor_init(rtems_boolean monitor_suspend)
+{
+    rtems_status_code status;
+    
+    status = rtems_task_create(rtems_build_name('R', 'M', 'O', 'N'),
+                               1, 0/*stack*/, RTEMS_NO_PREEMPT | RTEMS_INTERRUPT_LEVEL(0), RTEMS_DEFAULT_ATTRIBUTES, &rtems_monitor_task_id);
+    if (status != RTEMS_SUCCESSFUL)
+    {
+        printf("could not create monitor task\n");
+        goto done;
+    }
+
+    rtems_monitor_symbols_loadup();
+
+    status = rtems_task_start(rtems_monitor_task_id, rtems_monitor_task, monitor_suspend);
+    if (status != RTEMS_SUCCESSFUL)
+    {
+        printf("could not start monitor!\n");
+        goto done;
+    }
+
+done:
+}
+
+rtems_status_code
+rtems_monitor_suspend(rtems_interval timeout)
+{
+    rtems_event_set event_set;
+    rtems_status_code status;
+    
+    status = rtems_event_receive(MONITOR_WAKEUP_EVENT, RTEMS_DEFAULT_OPTIONS, timeout, &event_set);
+    return status;
+}
+
+void
+rtems_monitor_wakeup(void)
+{
+    rtems_status_code status;
+    
+    status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
+}
+
+
+/*
+ * Read and break up a monitor command
+ *
+ * We have to loop on the gets call, since it will return NULL under UNIX
+ *  RTEMS when we get a signal (eg: SIGALRM).
+ */
+
+int
+rtems_monitor_read_command(char *command,
+                           int  *argc,
+                           char **argv)
+{
+    printf("%s", MONITOR_PROMPT);  fflush(stdout);
+    while (gets(command) == (char *) 0)
+        ;
+    return rtems_monitor_make_argv(command, argc, argv);
+}
+
+void
+rtems_monitor_task(rtems_task_argument monitor_suspend)
+{
+    rtems_tcb *debugee = 0;
+    char command[513];
+    rtems_context *rp;
+    rtems_context_fp *fp;
+    char *cp;
+    int argc;
+    char *argv[64];        
+
+    if ((rtems_boolean) monitor_suspend)
+        (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
+
+    for (;;)
+    {
+        extern rtems_tcb * _Thread_Executing;
+        debugee = _Thread_Executing;
+        rp = &debugee->Registers;
+        fp = (rtems_context_fp *) debugee->fp_context;  /* possibly 0 */
+
+        if (0 == rtems_monitor_read_command(command, &argc, argv))
+            continue;
+        
+        if (STREQ(argv[0], "quit"))
+            rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
+        else if (STREQ(argv[0], "pause"))
+            rtems_monitor_suspend(1);
+
+#ifdef CPU_INVOKE_DEBUGGER
+        else if (STREQ(argv[0], "debug"))
+        {
+            CPU_INVOKE_DEBUGGER;
+        }
+#endif            
+        else if (STREQ(argv[0], "symbol"))
+        {
+            char *symbol;
+            char *value;
+
+            if (argc != 3)
+            {
+                printf("usage: symbol symname symvalue\n");
+                continue;
+            }
+
+            symbol = argv[1];
+            value = argv[2];
+            if (symbol && value)
+            {
+                rtems_symbol_t *sp;
+                sp = rtems_symbol_create(rtems_monitor_symbols,
+                                         symbol,
+                                         (rtems_unsigned32) strtoul(value, 0, 16));
+                if (sp)
+                    printf("symbol defined is at %p\n", sp);
+                else
+                    printf("could not define symbol\n");
+            }
+            else
+                printf("parsing error\n");
+        }
+        else
+        {
+            printf("Unrecognized command: '%s'\n", argv[0]);
+        }
+    }
+}
+
+/*
+ *  Function:   rtems_monitor_symbols_loadup
+ *
+ *  Description:
+ *      Create and load the monitor's symbol table.
+ *      We are reading the output format of 'gnm' which looks like this:
+ *
+ *              400a7068 ? _Rate_monotonic_Information
+ *              400a708c ? _Thread_Dispatch_disable_level
+ *              400a7090 ? _Configuration_Table
+ *
+ *
+ *      We ignore the type field.
+ *
+ *  Parameters:
+ *
+ *
+ *  Returns:
+ *
+ *
+ *  Side Effects:
+ *      Creates and fills in 'rtems_monitor_symbols' table
+ *
+ *  Notes:
+ *
+ *
+ *  Deficiencies/ToDo:
+ *      Someday this should know BFD
+ *              Maybe we could get objcopy to just copy the symbol areas
+ *              and copy that down.
+ *
+ */
+
+void
+rtems_monitor_symbols_loadup(void)
+{
+    FILE *fp;
+    char buffer[128];
+
+    rtems_monitor_symbols = rtems_symbol_table_create(10);
+    if (rtems_monitor_symbols == 0)
+        return;
+
+    fp = fdopen(8, "r");
+    if (fp == 0)
+        return;
+
+    while (fgets(buffer, sizeof(buffer) - 1, fp))
+    {
+        char *symbol;
+        char *value;
+        char *ignored_type;
+
+        value = strtok(buffer, " \t\n");
+        ignored_type = strtok(0, " \t\n");
+        symbol = strtok(0, " \t\n");
+
+        if (symbol && ignored_type && value)
+        {
+            rtems_symbol_t *sp;
+            sp = rtems_symbol_create(rtems_monitor_symbols,
+                                     symbol,
+                                     (rtems_unsigned32) strtoul(value, 0, 16));
+            if (sp == 0)
+            {
+                printf("could not define symbol\n");
+                goto done;
+            }
+        }
+        else
+        {
+            printf("parsing error\n");
+            goto done;
+        }
+    }
+
+done:
+}
Index: c/src/libmisc/monitor/mon-symbols.c
===================================================================
--- c/src/libmisc/monitor/mon-symbols.c	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
+++ c/src/libmisc/monitor/mon-symbols.c	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
@@ -0,0 +1,327 @@
+/*
+ *      @(#)symbols.c	1.3 - 95/04/24
+ *      
+ */
+
+/* #define qsort _quicksort */
+
+/*
+ *  File:	symbols.c
+ *
+ *  Description:
+ *    Symbol table manager for the RTEMS monitor.
+ *    These routines may be used by other system resources also.
+ *
+ *
+ *  TODO:
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rtems.h>
+
+#include "symbols.h"
+
+extern rtems_symbol_table_t *rtems_monitor_symbols;
+
+#ifdef RTEMS_DEBUG
+#define CHK_ADR_PTR(p)  \
+do { \
+    if (((p) < rtems_monitor_symbols->addresses) || \
+        ((p) >= (rtems_monitor_symbols->addresses + rtems_monitor_symbols->next))) \
+    { \
+        printf("bad address pointer %p\n", (p)); \
+        rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS); \
+    } \
+} while (0)
+
+#define CHK_NAME_PTR(p) \
+do { \
+    if (((p) < rtems_monitor_symbols->symbols) || \
+        ((p) >= (rtems_monitor_symbols->symbols + rtems_monitor_symbols->next))) \
+    { \
+        printf("bad symbol pointer %p\n", (p)); \
+        rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS); \
+    } \
+} while (0)
+#else
+#define CHK_ADR_PTR(p)
+#define CHK_NAME_PTR(p)
+#endif
+
+rtems_symbol_table_t *
+rtems_symbol_table_create()
+{
+    rtems_symbol_table_t *table;
+
+    table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t));
+    memset((void *) table, 0, sizeof(*table));
+
+    table->growth_factor = 30;          /* 30 percent */
+
+    return table;
+}
+
+void
+rtems_symbol_table_destroy(rtems_symbol_table_t *table)
+{
+    rtems_symbol_string_block_t *p, *pnext;
+
+    if (table)
+    {
+        if (table->addresses)
+            (void) free(table->addresses);
+        table->addresses = 0;
+
+        if (table->symbols)
+            (void) free(table->symbols);
+        table->symbols = 0;
+
+        p = table->string_buffer_head;
+        while (p)
+        {
+            pnext = p->next;
+            free(p);
+            p = pnext;
+        }
+        table->string_buffer_head = 0;
+        table->string_buffer_current = 0;
+
+        free(table);
+    }
+}
+
+rtems_symbol_t *
+rtems_symbol_create(
+    rtems_symbol_table_t *table,
+    char                 *name,
+    rtems_unsigned32     value
+    )
+{
+    int symbol_length;
+    size_t newsize;
+    rtems_symbol_t *sp;
+
+    symbol_length = strlen(name) + 1;   /* include '\000' in length */
+
+    /* need to grow the table? */
+    if (table->next >= table->size)
+    {
+        if (table->size == 0)
+            newsize = 100;
+        else
+            newsize = table->size + (table->size / (100 / table->growth_factor));
+
+        table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t));
+        if (table->addresses == 0)        /* blew it; lost orig */
+            goto failed;
+
+        table->symbols = (rtems_symbol_t *) realloc((void *) table->symbols, newsize * sizeof(rtems_symbol_t));
+        if (table->symbols == 0)        /* blew it; lost orig */
+            goto failed;
+
+        table->size = newsize;
+    }
+
+    sp = &table->addresses[table->next];
+    sp->value = value;
+
+    /* Have to add it to string pool */
+    /* need to grow pool? */
+
+    if ((table->string_buffer_head == 0) ||
+        (table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE)
+    {
+        rtems_symbol_string_block_t *p;
+
+        p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t));
+        if (p == 0)
+            goto failed;
+        p->next = 0;
+        if (table->string_buffer_head == 0)
+            table->string_buffer_head = p;
+        else
+            table->string_buffer_current->next = p;
+        table->string_buffer_current = p;
+
+        table->strings_next = 0;
+    }
+
+    sp->name = table->string_buffer_current->buffer + table->strings_next;
+    (void) strcpy(sp->name, name);
+
+    table->strings_next += symbol_length;
+
+    table->symbols[table->next] = *sp;
+
+    table->sorted = 0;
+    table->next++;
+
+    return sp;
+
+/* XXX Not sure what to do here.  We've possibly destroyed the initial
+   symbol table due to realloc failure */
+failed:
+    return 0;
+}
+
+/*
+ * Qsort entry point for compare by address
+ */
+
+int
+rtems_symbol_compare(const void *e1,
+                     const void *e2)
+{
+    rtems_symbol_t *s1, *s2;
+    s1 = (rtems_symbol_t *) e1;
+    s2 = (rtems_symbol_t *) e2;
+
+    CHK_ADR_PTR(s1);
+    CHK_ADR_PTR(s2);
+
+    if (s1->value < s2->value)
+        return -1;
+    if (s1->value > s2->value)
+        return 1;
+    return 0;
+}
+
+/*
+ * Qsort entry point for compare by string name (case independent)
+ */
+
+int
+rtems_symbol_string_compare(const void *e1,
+                            const void *e2)
+{
+    rtems_symbol_t *s1, *s2;
+    s1 = (rtems_symbol_t *) e1;
+    s2 = (rtems_symbol_t *) e2;
+
+    CHK_NAME_PTR(s1);
+    CHK_NAME_PTR(s2);
+
+    return strcasecmp(s1->name, s2->name);
+}
+
+
+/*
+ * Sort the symbol table using qsort
+ */
+
+void
+rtems_symbol_sort(rtems_symbol_table_t *table)
+{
+#ifdef simhppa
+    printf("Sorting symbols ... ");         /* so slow we need a msg */
+    fflush(stdout);
+#endif
+
+    qsort((void *) table->addresses, (size_t) table->next,
+          sizeof(rtems_symbol_t), rtems_symbol_compare);
+
+    qsort((void *) table->symbols, (size_t) table->next,
+          sizeof(rtems_symbol_t), rtems_symbol_string_compare);
+
+#ifdef simhppa
+    /* so slow we need a msg */
+    printf("done\n");
+#endif
+
+    table->sorted = 1;
+}
+
+/*
+ * Search the symbol table by address
+ * This code based on CYGNUS newlib bsearch, but changed
+ * to allow for finding closest symbol <= key
+ */
+
+rtems_symbol_t *
+rtems_symbol_value_lookup(
+    rtems_symbol_table_t *table,
+    rtems_unsigned32      value
+  )
+{
+    rtems_symbol_t *sp;
+    rtems_symbol_t *base;
+    rtems_symbol_t *best = 0;
+    rtems_unsigned32 distance;
+    rtems_unsigned32 best_distance = ~0;
+    rtems_unsigned32 elements;
+
+    if ((table == 0) || (table->size == 0))
+        return 0;
+
+    if (table->sorted == 0)
+        rtems_symbol_sort(table);
+
+    base = table->addresses;
+    elements = table->next;
+
+    while (elements)
+    {
+        sp = base + (elements / 2);
+        if (value < sp->value)
+            elements /= 2;
+        else if (value > sp->value)
+        {
+            distance = value - sp->value;
+            if (distance < best_distance)
+            {
+                best_distance = distance;
+                best = sp;
+            }
+            base = sp + 1;
+            elements = (elements / 2) - (elements % 2 ? 0 : 1);
+        }
+        else
+            return sp;
+    }
+
+    if (value == base->value)
+        return base;
+
+    return best;
+}
+
+/*
+ * Search the symbol table by string name (case independent)
+ */
+
+rtems_symbol_t *
+rtems_symbol_name_lookup(
+    rtems_symbol_table_t *table,
+    char                 *name
+  )
+{
+    rtems_symbol_t *sp = 0;
+    rtems_symbol_t  key;
+
+    if ((table == 0) || (name == 0))
+        goto done;
+
+    if (table->sorted == 0)
+    {
+        rtems_symbol_sort(table);
+    }
+
+    /*
+     * dummy up one for bsearch()
+     */
+
+    key.name = name;
+    key.value = 0;
+
+    sp = (rtems_symbol_t *) bsearch((const void *) &key,
+                                    (const void *) table->symbols,
+                                    (size_t) table->next,
+                                    sizeof(rtems_symbol_t),
+                                    rtems_symbol_string_compare);
+
+done:
+    return sp;
+}
+
Index: c/src/libmisc/monitor/monitor.h
===================================================================
--- c/src/libmisc/monitor/monitor.h	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
+++ c/src/libmisc/monitor/monitor.h	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
@@ -0,0 +1,38 @@
+/*
+ *      @(#)monitor.h	1.2 - 95/04/24
+ *      
+ */
+
+/*
+ *  File:	monitor.h
+ *
+ *  Description:
+ *    The RTEMS monitor task include file.
+ *
+ *
+ *
+ *  TODO:
+ *
+ */
+
+#ifndef __MONITOR_H
+#define __MONITOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void    rtems_monitor_init(rtems_boolean monitor_suspend);
+void    rtems_monitor_wakeup(void);
+void    rtems_monitor_task(rtems_task_argument monitor_suspend);
+void    rtems_monitor_symbols_loadup(void);
+
+extern rtems_unsigned32        rtems_monitor_task_id;
+
+extern rtems_symbol_table_t *rtems_monitor_symbols;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ! __MONITOR_H */
Index: c/src/libmisc/monitor/symbols.h
===================================================================
--- c/src/libmisc/monitor/symbols.h	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
+++ c/src/libmisc/monitor/symbols.h	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
@@ -0,0 +1,80 @@
+/*
+ *  File:       symbols.h
+ *
+ *  Description:
+ *      Entry points for symbol table routines.
+ *
+ *
+ *
+ *  TODO:
+ *
+ */
+
+#ifndef _INCLUDE_SYMBOLS_H
+#define _INCLUDE_SYMBOLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    rtems_unsigned32 value;
+    char            *name;
+} rtems_symbol_t;
+
+#define SYMBOL_STRING_BLOCK_SIZE 4080
+typedef struct rtems_symbol_string_block_s {
+    struct rtems_symbol_string_block_s *next;
+    char   buffer[SYMBOL_STRING_BLOCK_SIZE];
+} rtems_symbol_string_block_t;
+
+typedef struct {
+
+    rtems_unsigned32 sorted;            /* are symbols sorted right now? */
+
+    rtems_unsigned32 growth_factor;     /* % to grow by when needed */
+
+    rtems_unsigned32 next;              /* next symbol slot to use when adding */
+    rtems_unsigned32 size;              /* max # of symbols */
+
+    /*
+     * Symbol list -- sorted by address (when we do a lookup)
+     */
+
+    rtems_symbol_t  *addresses;         /* symbol array by address */
+
+    /*
+     * String list -- sorted by name (when we do a lookup)
+     * This is a duplicate of the info in table->addresses, but it's
+     * pretty small, so I don't worry about it.
+     */
+
+    rtems_symbol_t  *symbols;           /* symbol array */
+
+    /*
+     * String pool, unsorted, a list of blocks of string data
+     */
+
+    rtems_symbol_string_block_t *string_buffer_head;
+    rtems_symbol_string_block_t *string_buffer_current;
+    rtems_unsigned32 strings_next;      /* next byte to use in this block */
+
+} rtems_symbol_table_t;
+
+void                  rtems_symbol_table_destroy(rtems_symbol_table_t *table);
+rtems_symbol_table_t *rtems_symbol_table_create();
+rtems_symbol_t       *rtems_symbol_create(rtems_symbol_table_t *,
+                                          char *, rtems_unsigned32);
+rtems_symbol_t       *rtems_symbol_value_lookup(rtems_symbol_table_t *,
+                                                rtems_unsigned32);
+rtems_symbol_t       *rtems_symbol_name_lookup(rtems_symbol_table_t *,
+                                                char *);
+
+#define rtems_symbol_name(sp)   ((sp)->name)
+#define rtems_symbol_value(sp)  ((sp)->value)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_SYMBOLS_H */
