Main Page | File List | Globals | Related Pages

utils.c

Go to the documentation of this file.
00001 /* 00002 * $Id: utils.c,v 1.19 2003/12/01 09:10:17 troth 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 00361 if (func == NULL) 00362 avr_error ("no iteration func supplied"); 00363 00364 while (node) 00365 { 00366 if ((*func) (node->data, user_data)) 00367 { 00368 /* remove node */ 00369 head = dlist_delete (head, node->data, dlist_iterator_cmp); 00370 } 00371 00372 node = node->next; 00373 } 00374 00375 return head; 00376 }

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.