pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00036 /* lists.h 147 2007-04-09 00:44:09Z selinger */ 00037 00038 #ifndef PCB_HID_GCODE_LISTS_H 00039 #define PCB_HID_GCODE_LISTS_H 00040 00048 #define MACRO_BEGIN do { 00049 #define MACRO_END } while (0) 00050 00051 /* ---------------------------------------------------------------------- */ 00052 /* macros for singly-linked lists */ 00053 00056 #define list_forall(elt, list) for (elt=list; elt!=NULL; elt=elt->next) 00057 00061 #define list_find(elt, list, c) \ 00062 MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END 00063 00067 #define list_forall2(elt, list, hook) \ 00068 for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next) 00069 00073 #define list_find2(elt, list, c, hook) \ 00074 MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END 00075 00079 #define _list_forall_hook(list, hook) \ 00080 for (hook=&list; *hook!=NULL; hook=&(*hook)->next) 00081 00087 #define _list_find_hook(list, c, hook) \ 00088 MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END 00089 00093 #define list_insert_athook(elt, hook) \ 00094 MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END 00095 00099 #define list_insert_beforehook(elt, hook) \ 00100 MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END 00101 00106 #define list_unlink_athook(list, elt, hook) \ 00107 MACRO_BEGIN \ 00108 elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\ 00109 MACRO_END 00110 00115 #define list_unlink(listtype, list, elt) \ 00116 MACRO_BEGIN \ 00117 listtype **_hook; \ 00118 _list_find_hook(list, *_hook==elt, _hook); \ 00119 list_unlink_athook(list, elt, _hook); \ 00120 MACRO_END 00121 00125 #define list_prepend(list, elt) \ 00126 MACRO_BEGIN elt->next = list; list = elt; MACRO_END 00127 00131 #define list_append(listtype, list, elt) \ 00132 MACRO_BEGIN \ 00133 listtype **_hook; \ 00134 _list_forall_hook(list, _hook) {} \ 00135 list_insert_athook(elt, _hook); \ 00136 MACRO_END 00137 00141 #define list_unlink_cond(listtype, list, elt, c) \ 00142 MACRO_BEGIN \ 00143 listtype **_hook; \ 00144 list_find2(elt, list, c, _hook); \ 00145 list_unlink_athook(list, elt, _hook); \ 00146 MACRO_END 00147 00154 #define list_nth(elt, list, n) \ 00155 MACRO_BEGIN \ 00156 int _x; /* only evaluate n once */ \ 00157 for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {} \ 00158 MACRO_END 00159 00166 #define list_nth_hook(elt, list, n, hook) \ 00167 MACRO_BEGIN \ 00168 int _x; /* only evaluate n once */ \ 00169 for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {} \ 00170 MACRO_END 00171 00175 #define list_length(listtype, list, n) \ 00176 MACRO_BEGIN \ 00177 listtype *_elt; \ 00178 n=0; \ 00179 list_forall(_elt, list) \ 00180 n++; \ 00181 MACRO_END 00182 00189 #define list_index(list, n, elt, c) \ 00190 MACRO_BEGIN \ 00191 n=0; \ 00192 list_forall(elt, list) { \ 00193 if (c) break; \ 00194 n++; \ 00195 } \ 00196 if (!elt) \ 00197 n=-1; \ 00198 MACRO_END 00199 00204 #define list_count(list, n, elt, c) \ 00205 MACRO_BEGIN \ 00206 n=0; \ 00207 list_forall(elt, list) { \ 00208 if (c) n++; \ 00209 } \ 00210 MACRO_END 00211 00217 #define list_forall_unlink(elt, list) \ 00218 for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list) 00219 00223 #define list_reverse(listtype, list) \ 00224 MACRO_BEGIN \ 00225 listtype *_list1=NULL, *elt; \ 00226 list_forall_unlink(elt, list) \ 00227 list_prepend(_list1, elt); \ 00228 list = _list1; \ 00229 MACRO_END 00230 00249 #define list_insert_ordered(listtype, list, elt, tmp, cond) \ 00250 MACRO_BEGIN \ 00251 listtype **_hook; \ 00252 _list_find_hook(list, (tmp=*_hook, (cond)), _hook); \ 00253 list_insert_athook(elt, _hook); \ 00254 MACRO_END 00255 00267 #define list_sort(listtype, list, a, b, cond) \ 00268 MACRO_BEGIN \ 00269 listtype *_newlist=NULL; \ 00270 list_forall_unlink(a, list) \ 00271 list_insert_ordered(listtype, _newlist, a, b, cond); \ 00272 list = _newlist; \ 00273 MACRO_END 00274 00284 #define list_mergesort(listtype, list, a, b, cond) \ 00285 MACRO_BEGIN \ 00286 listtype *_elt, **_hook1; \ 00287 \ 00288 for (_elt=list; _elt; _elt=_elt->next1) { \ 00289 _elt->next1 = _elt->next; \ 00290 _elt->next = NULL; \ 00291 } \ 00292 do { \ 00293 _hook1 = &(list); \ 00294 while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) { \ 00295 _elt = b->next1; \ 00296 _list_merge_cond(listtype, a, b, cond, *_hook1); \ 00297 _hook1 = &((*_hook1)->next1); \ 00298 *_hook1 = _elt; \ 00299 } \ 00300 } while (_hook1 != &(list)); \ 00301 MACRO_END 00302 00308 #define _list_merge_cond(listtype, a, b, cond, result) \ 00309 MACRO_BEGIN \ 00310 listtype **_hook; \ 00311 _hook = &(result); \ 00312 while (1) { \ 00313 if (a==NULL) { \ 00314 *_hook = b; \ 00315 break; \ 00316 } else if (b==NULL) { \ 00317 *_hook = a; \ 00318 break; \ 00319 } else if (cond) { \ 00320 *_hook = a; \ 00321 _hook = &(a->next); \ 00322 a = a->next; \ 00323 } else { \ 00324 *_hook = b; \ 00325 _hook = &(b->next); \ 00326 b = b->next; \ 00327 } \ 00328 } \ 00329 MACRO_END 00330 00331 /* ---------------------------------------------------------------------- */ 00332 /* macros for doubly-linked lists */ 00333 00334 #define dlist_append(head, end, elt) \ 00335 MACRO_BEGIN \ 00336 elt->prev = end; \ 00337 elt->next = NULL; \ 00338 if (end) { \ 00339 end->next = elt; \ 00340 } else { \ 00341 head = elt; \ 00342 } \ 00343 end = elt; \ 00344 MACRO_END 00345 00351 #define dlist_forall_unlink(elt, head, end) \ 00352 for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head) 00353 00357 #define dlist_unlink_first(head, end, elt) \ 00358 MACRO_BEGIN \ 00359 elt = head; \ 00360 if (head) { \ 00361 head = head->next; \ 00362 if (head) { \ 00363 head->prev = NULL; \ 00364 } else { \ 00365 end = NULL; \ 00366 } \ 00367 elt->prev = NULL; \ 00368 elt->next = NULL; \ 00369 } \ 00370 MACRO_END 00371 00372 #endif /* PCB_HID_GCODE_LISTS_H */