Main Page

- Main Page
- Related Pages
- Files

- File List
- Globals

# utils.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: utils.c,v 1.20 2008/03/19 22:39:02 joerg_wunsch Exp $
    00003  *
    00004  ****************************************************************************
    00005  *
    00006  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
    00007  * Copyright (C) 2001, 2002, 2003  Theodore A. Roth
    00008  *
    00009  * This program is free software; you can redistribute it and/or modify
    00010  * it under the terms of the GNU General Public License as published by
    00011  * the Free Software Foundation; either version 2 of the License, or
    00012  * (at your option) any later version.
    00013  *
    00014  * This program is distributed in the hope that it will be useful,
    00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00017  * GNU General Public License for more details.
    00018  *
    00019  * You should have received a copy of the GNU General Public License
    00020  * along with this program; if not, write to the Free Software
    00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00022  *
    00023  ****************************************************************************
    00024  */
    00025
    00026 /**
    00027  * \file utils.c
    00028  * \brief Utility functions.
    00029  *
    00030  * This module provides general purpose utilities.
    00031  */
    00032
    00033 #include <config.h>
    00034
    00035 #include <stdio.h>
    00036 #include <stdlib.h>
    00037 #include <unistd.h>
    00038 #include <string.h>
    00039 #include <errno.h>
    00040 #include <sys/time.h>
    00041
    00042 #include "avrerror.h"
    00043 #include "avrmalloc.h"
    00044 #include "avrclass.h"
    00045 #include "utils.h"
    00046
    00047 /** \brief Utility function to convert a string to a FileFormatType code. */
    00048
    00049 int
    00050 str2ffmt (char *str)
    00051 {
    00052     if (strncmp (str, "bin", 3) == 0)
    00053         return FFMT_BIN;
    00054     if (strncmp (str, "ihex", 4) == 0)
    00055         return FFMT_IHEX;
    00056     if (strncmp (str, "elf", 3) == 0)
    00057         return FFMT_ELF;
    00058
    00059     return -1;
    00060 }
    00061
    00062 /** \brief Set a bit in src to 1 if val != 0, clears bit if val == 0. */
    00063
    00064 extern inline uint8_t set_bit_in_byte (uint8_t src, int bit, int val);
    00065
    00066 /** \brief Set a bit in src to 1 if val != 0, clears bit if val == 0. */
    00067
    00068 extern inline uint16_t set_bit_in_word (uint16_t src, int bit, int val);
    00069
    00070 /** \brief Return the number of milliseconds of elapsed program time.
    00071
    00072     \return an unsigned 64 bit number. Time zero is not well
    00073     defined, so only time differences should be used. */
    00074
    00075 uint64_t
    00076 get_program_time (void)
    00077 {
    00078     uint64_t result;
    00079     struct timeval tv;
    00080
    00081     if (gettimeofday (&tv, NULL) < 0)
    00082         avr_error ("Failed to get program time.");
    00083
    00084     result = ((uint64_t) tv.tv_sec * 1000) + ((uint64_t) tv.tv_usec / 1000);
    00085
    00086     return result;
    00087 }
    00088
    00089 /***************************************************************************\
    00090  *
    00091  * DList(AvrClass) Methods : A doubly linked list.
    00092  *
    00093 \***************************************************************************/
    00094
    00095 static DList *dlist_new_node (AvrClass *data);
    00096 static void dlist_construct_node (DList *node, AvrClass *data);
    00097 static void dlist_destroy_node (void *node);
    00098
    00099 #ifndef DOXYGEN                 /* Don't expose to doxygen, structure is
    00100                                    opaque. */
    00101
    00102 struct _DList
    00103 {
    00104     AvrClass parent;
    00105     struct _DList *prev;
    00106     struct _DList *next;
    00107     AvrClass *data;
    00108 };
    00109
    00110 #endif
    00111
    00112 static DList *
    00113 dlist_new_node (AvrClass *data)
    00114 {
    00115     DList *node;
    00116
    00117     node = avr_new (DList, 1);
    00118     dlist_construct_node (node, data);
    00119     class_overload_destroy ((AvrClass *)node, dlist_destroy_node);
    00120
    00121     return node;
    00122 }
    00123
    00124 static void
    00125 dlist_construct_node (DList *node, AvrClass *data)
    00126 {
    00127     if (node == NULL)
    00128         avr_error ("passed null ptr");
    00129
    00130     class_construct ((AvrClass *)node);
    00131
    00132     node->prev = NULL;
    00133     node->next = NULL;
    00134
    00135     node->data = data;
    00136 }
    00137
    00138 static void
    00139 dlist_destroy_node (void *node)
    00140 {
    00141     DList *_node = (DList *)node;
    00142
    00143     if (_node == NULL)
    00144         return;
    00145
    00146     class_unref (_node->data);
    00147
    00148     class_destroy (node);
    00149 }
    00150
    00151 /** \brief Add a new node to the end of the list.
    00152
    00153    If cmp argument is not NULL, use cmp() to see if node already exists and
    00154    don't add node if it exists.
    00155
    00156    It is the responsibility of this function to unref data if not added. */
    00157
    00158 DList *
    00159 dlist_add (DList *head, AvrClass *data, DListFP_Cmp cmp)
    00160 {
    00161     DList *node = head;
    00162
    00163     if (head == NULL)
    00164         /* The list is empty, make new node the head. */
    00165         return dlist_new_node (data);
    00166
    00167     /* Walk the list to find the end */
    00168
    00169     while (node)
    00170     {
    00171         if (cmp && ((*cmp) (node->data, data) == 0))
    00172         {
    00173             /* node already exists and we were asked to keep nodes unique */
    00174             class_unref (data);
    00175             break;
    00176         }
    00177
    00178         if (node->next == NULL)
    00179         {
    00180             /* at the tail */
    00181             node->next = dlist_new_node (data);
    00182             node->next->prev = node;
    00183             break;
    00184         }
    00185
    00186         /* move on to next node */
    00187         node = node->next;
    00188     }
    00189
    00190     return head;
    00191 }
    00192
    00193 /** \brief Add a new node at the head of the list. */
    00194
    00195 DList *
    00196 dlist_add_head (DList *head, AvrClass *data)
    00197 {
    00198     DList *node = dlist_new_node (data);;
    00199
    00200     if (head)
    00201     {
    00202         head->prev = node;
    00203         node->next = head;
    00204     }
    00205
    00206     return node;
    00207 }
    00208
    00209 /** \brief Conditionally delete a node from the list.
    00210
    00211     Delete a node from the list if the node's data matches the specified
    00212     data. Returns the head of the modified list. */
    00213
    00214 DList *
    00215 dlist_delete (DList *head, AvrClass *data, DListFP_Cmp cmp)
    00216 {
    00217     DList *node = head;
    00218
    00219     if (cmp == NULL)
    00220         avr_error ("compare function not specified");
    00221
    00222     while (node)
    00223     {
    00224         if ((*cmp) (node->data, data) == 0)
    00225         {
    00226             if ((node->prev == NULL) && (node->next == NULL))
    00227             {
    00228                 /* deleting only node in list (node is head and tail) */
    00229                 head = NULL;
    00230             }
    00231             else if (node->prev == NULL)
    00232             {
    00233                 /* node is head, but other nodes exist */
    00234                 node->next->prev = NULL;
    00235                 head = node->next;
    00236             }
    00237             else if (node->next == NULL)
    00238             {
    00239                 /* node is tail, but other nodes exist */
    00240                 node->prev->next = NULL;
    00241             }
    00242             else
    00243             {
    00244                 /* node is not head nor tail */
    00245                 node->prev->next = node->next;
    00246                 node->next->prev = node->prev;
    00247             }
    00248
    00249             /* this will also unref the node->data */
    00250             class_unref ((AvrClass *)node);
    00251
    00252             return head;
    00253         }
    00254
    00255         /* move on to next node */
    00256         node = node->next;
    00257     }
    00258
    00259     /* if we get here, data wasn't found, just return original head */
    00260     return head;
    00261 }
    00262
    00263 /** \brief Blow away the entire list. */
    00264
    00265 void
    00266 dlist_delete_all (DList *head)
    00267 {
    00268     DList *node;
    00269
    00270     while (head)
    00271     {
    00272         node = head;
    00273         head = head->next;
    00274
    00275         class_unref ((AvrClass *)node);
    00276     }
    00277 }
    00278
    00279 /** \brief Lookup an item in the list.
    00280
    00281     Walk the list pointed to by head and return a pointer to the data if
    00282     found. If not found, return NULL.
    00283
    00284     \param head The head of the list to be iterated.
    00285     \param data The data to be passed to the func when it is applied.
    00286     \param cmp  A function to be used for comparing the items.
    00287
    00288     \return     A pointer to the data found, or NULL if not found. */
    00289
    00290 AvrClass *
    00291 dlist_lookup (DList *head, AvrClass *data, DListFP_Cmp cmp)
    00292 {
    00293     DList *node = head;
    00294
    00295     if (cmp == NULL)
    00296         avr_error ("compare function not specified");
    00297
    00298     while (node)
    00299     {
    00300         if ((*cmp) (node->data, data) == 0)
    00301             return node->data;
    00302
    00303         node = node->next;
    00304     }
    00305
    00306     /* If we get here, no node was found, return NULL. */
    00307
    00308     return NULL;
    00309 }
    00310
    00311 /** \brief Extract the data from the head of the list.
    00312
    00313     Returns the data element for the head of the list. If the list is empty,
    00314     return a NULL pointer.
    00315
    00316     \param head The head of the list.
    00317
    00318     \return     A pointer to the data found, or NULL if not found. */
    00319
    00320 AvrClass *
    00321 dlist_get_head_data (DList *head)
    00322 {
    00323
    00324     if (head == NULL)
    00325     {
    00326         return NULL;
    00327     }
    00328
    00329     return head->data;
    00330 }
    00331
    00332 /* a simple node compare function for the iterator. */
    00333
    00334 static int
    00335 dlist_iterator_cmp (AvrClass *n1, AvrClass *n2)
    00336 {
    00337     /* Since this is only used in the iterator, we are guaranteed that it is
    00338        safe to compare data pointers because both n1 and n2 came from the
    00339        list. */
    00340
    00341     return (int)(n1 - n2);
    00342 }
    00343
    00344 /** \brief Iterate over all elements of the list.
    00345
    00346     For each element, call the user supplied iterator function and pass it the
    00347     node data and the user_data. If the iterator function return non-zero,
    00348     remove the node from the list.
    00349
    00350     \param head The head of the list to be iterated.
    00351     \param func The function to be applied.
    00352     \param user_data The data to be passed to the func when it is applied.
    00353
    00354     \return A pointer to the head of the possibly modified list. */
    00355
    00356 DList *
    00357 dlist_iterator (DList *head, DListFP_Iter func, void *user_data)
    00358 {
    00359     DList *node = head;
    00360     DList *n;
    00361
    00362     if (func == NULL)
    00363         avr_error ("no iteration func supplied");
    00364
    00365     while (node)
    00366     {
    00367         n = node->next;
    00368
    00369         if ((*func) (node->data, user_data))
    00370         {
    00371             /* remove node */
    00372             head = dlist_delete (head, node->data, dlist_iterator_cmp);
    00373         }
    00374
    00375         node = n;
    00376     }
    00377
    00378     return head;
    00379 }

Automatically generated by Doxygen 1.7.2 on Wed Aug 15 2012.