gattrib
|
00001 00002 /*----------------------------------------------------------------*/ 00010 /* 00011 * Demonstration code for sorting a linked list. 00012 * 00013 * The algorithm used is Mergesort, because that works really well 00014 * on linked lists, without requiring the O(N) extra space it needs 00015 * when you do it on arrays. 00016 * 00017 * This code can handle singly and doubly linked lists, and 00018 * circular and linear lists too. For any serious application, 00019 * you'll probably want to remove the conditionals on `is_circular' 00020 * and `is_double' to adapt the code to your own purpose. 00021 * 00022 */ 00023 00024 /* 00025 * This file is copyright 2001 Simon Tatham. 00026 * 00027 * Permission is hereby granted, free of charge, to any person 00028 * obtaining a copy of this software and associated documentation 00029 * files (the "Software"), to deal in the Software without 00030 * restriction, including without limitation the rights to use, 00031 * copy, modify, merge, publish, distribute, sublicense, and/or 00032 * sell copies of the Software, and to permit persons to whom the 00033 * Software is furnished to do so, subject to the following 00034 * conditions: 00035 * 00036 * The above copyright notice and this permission notice shall be 00037 * included in all copies or substantial portions of the Software. 00038 * 00039 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00040 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 00041 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00042 * NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR 00043 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 00044 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00045 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00046 * SOFTWARE. 00047 */ 00048 00049 /* --- We don't need these 'cause they are already defined elsewhere --- 00050 * #define FALSE 0 00051 * #define TRUE 1 00052 */ 00053 00054 #ifdef HAVE_CONFIG_H 00055 #include "config.h" 00056 #endif 00057 00058 #include <stdio.h> 00059 #include <ctype.h> 00060 00061 #ifdef HAVE_STRING_H 00062 #include <string.h> 00063 #endif 00064 00065 /*------------------------------------------------------------------ 00066 * Gattrib specific includes 00067 *------------------------------------------------------------------*/ 00068 #include <libgeda/libgeda.h> /* geda library fcns */ 00069 #include "../include/struct.h" /* typdef and struct declarations */ 00070 #include "../include/prototype.h" /* function prototypes */ 00071 #include "../include/globals.h" 00072 00073 #ifdef HAVE_LIBDMALLOC 00074 #include <dmalloc.h> 00075 #endif 00076 00077 00078 /*----------------------------------------------------------------*/ 00086 /*----------------------------------------------------------------*/ 00087 int cmp(STRING_LIST *al, STRING_LIST *bl) { 00088 char *a = al->data; 00089 char *b = bl->data; 00090 00091 if (al->pos != bl->pos) 00092 return al->pos - bl->pos; 00093 00094 while (*a && *b) 00095 { 00096 if (isdigit ((int) *a) && isdigit ((int) *b)) 00097 { 00098 int ia = atoi (a); 00099 int ib = atoi (b); 00100 if (ia != ib) 00101 return ia - ib; 00102 while (isdigit ((int) *a)) 00103 a++; 00104 while (isdigit ((int) *b)) 00105 b++; 00106 } 00107 else if (tolower ((int) *a) != tolower ((int) *b)) 00108 return tolower ((int) *a) - tolower ((int) *b); 00109 a++; 00110 b++; 00111 } 00112 if (*a) 00113 return 1; 00114 if (*b) 00115 return -1; 00116 return 0; 00117 } 00118 00119 /*----------------------------------------------------------------*/ 00138 /*----------------------------------------------------------------*/ 00139 STRING_LIST *listsort(STRING_LIST *list, int is_circular, int is_double) { 00140 STRING_LIST *p, *q, *e, *tail, *oldhead; 00141 int insize, nmerges, psize, qsize, i; 00142 00143 /* 00144 * Silly special case: if `list' was passed in as NULL, return 00145 * NULL immediately. 00146 */ 00147 if (!list) 00148 return NULL; 00149 00150 insize = 1; 00151 00152 while (1) { 00153 p = list; 00154 oldhead = list; /* only used for circular linkage */ 00155 list = NULL; 00156 tail = NULL; 00157 00158 nmerges = 0; /* count number of merges we do in this pass */ 00159 00160 while (p) { 00161 nmerges++; /* there exists a merge to be done */ 00162 /* step `insize' places along from p */ 00163 q = p; 00164 psize = 0; 00165 for (i = 0; i < insize; i++) { 00166 psize++; 00167 if (is_circular) 00168 q = (q->next == oldhead ? NULL : q->next); 00169 else 00170 q = q->next; 00171 if (!q) break; 00172 } 00173 00174 /* if q hasn't fallen off end, we have two lists to merge */ 00175 qsize = insize; 00176 00177 /* now we have two lists; merge them */ 00178 while (psize > 0 || (qsize > 0 && q)) { 00179 00180 /* decide whether next element of merge comes from p or q */ 00181 if (psize == 0) { 00182 /* p is empty; e must come from q. */ 00183 e = q; q = q->next; qsize--; 00184 if (is_circular && q == oldhead) q = NULL; 00185 } else if (qsize == 0 || !q) { 00186 /* q is empty; e must come from p. */ 00187 e = p; p = p->next; psize--; 00188 if (is_circular && p == oldhead) p = NULL; 00189 } else if (cmp(p,q) <= 0) { 00190 /* First element of p is lower (or same); 00191 * e must come from p. */ 00192 e = p; p = p->next; psize--; 00193 if (is_circular && p == oldhead) p = NULL; 00194 } else { 00195 /* First element of q is lower; e must come from q. */ 00196 e = q; q = q->next; qsize--; 00197 if (is_circular && q == oldhead) q = NULL; 00198 } 00199 00200 /* add the next element to the merged list */ 00201 if (tail) { 00202 tail->next = e; 00203 } else { 00204 list = e; 00205 } 00206 if (is_double) { 00207 /* Maintain reverse pointers in a doubly linked list. */ 00208 e->prev = tail; 00209 } 00210 tail = e; 00211 } 00212 00213 /* now p has stepped `insize' places along, and q has too */ 00214 p = q; 00215 } 00216 if (is_circular) { 00217 tail->next = list; 00218 if (is_double) 00219 list->prev = tail; 00220 } else 00221 tail->next = NULL; 00222 00223 /* If we have done only one merge, we're finished. */ 00224 if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ 00225 return list; 00226 00227 /* Otherwise repeat, merging lists twice the size */ 00228 insize *= 2; 00229 } 00230 } 00231