NEURON
list.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /* /local/src/master/nrn/src/modlunit/list.c,v 1.3 1997/11/24 16:19:10 hines Exp */
3 
4 /* The following routines support the concept of a list.
5 That is, one can insert at the head of a list or append to the tail of a
6 list with linsert<type>() and lappend<type>().
7 
8 In addition, one can insert an item before a known item and it will be
9 placed in the proper list.
10 
11 Items point to strings, symbols, etc. Note that more than one item in the
12 same or several lists can point to the same string, symbol.
13 
14 Finally, knowing an item, one can determine the preceding and following
15 items with next() and prev().
16 
17 Deletion, replacement and moving blocks of items is also supported.
18 */
19 /* For model, makelist and append have been added */
20 /* Implementation
21  The list is a doubly linked list. A special item with element 0 is
22  always at the tail of the list and is denoted as the List pointer itself.
23  list->next point to the first item in the list and
24  list->prev points to the last item in the list.
25  i.e. the list is circular
26  Note that in an empty list next and prev points to itself.
27 
28 It is intended that this implementation be hidden from the user via the
29 following function calls.
30 */
31 
32 #include <stdlib.h>
33 #include <cstring>
34 #include "model.h"
35 #include "parse1.hpp"
36 
37 #define DEBUG 0
38 #if DEBUG
39 static int debugtoken = 1;
40 #else
41 static int debugtoken = 0;
42 #endif
43 
44 static Item* newitem() {
45  return (Item*) emalloc(sizeof(Item));
46 }
47 
49  Item* i;
50  i = newitem();
51  i->prev = i;
52  i->next = i;
53  i->element = (void*) 0;
54  i->itemtype = 0;
55  return (List*) i;
56 }
57 
58 void freelist(List** plist) /*free the list but not the elements*/
59 {
60  Item *i1, *i2;
61  if (!(*plist)) {
62  return;
63  }
64  for (i1 = (*plist)->next; i1 != *plist; i1 = i2) {
65  i2 = i1->next;
66  free(i1);
67  }
68  free(*plist);
69  *plist = (List*) 0;
70 }
71 
72 static Item* linkitem(Item* item) {
73  Item* i;
74 
75  i = newitem();
76  i->prev = item->prev;
77  i->next = item;
78  item->prev = i;
79  i->prev->next = i;
80  return i;
81 }
82 
83 Item* car(List* list) {
84  Item* q = (Item*) list;
85  assert(q && q->itemtype == 0);
86  return next(q);
87 }
88 
89 Item* next(Item* item) {
90  assert(item->next->itemtype); /* never return the list item */
91  return item->next;
92 }
93 
94 Item* prev(Item* item) {
95  assert(item->prev->itemtype); /* never return the list item */
96  return item->prev;
97 }
98 
99 Item* insertstr(Item* item, const char* str) /* insert a copy of the string before item */
100 /* a copy is made because strings are often assembled into a reusable buffer*/
101 {
102  Item* i;
103 
104  i = linkitem(item);
105  i->element = (void*) stralloc(str, (char*) 0);
106  i->itemtype = STRING;
107  return i;
108 }
109 
110 Item* insertitem(Item* item, Item* itm) /* insert a item pointer before item */
111 {
112  Item* i;
113 
114  i = linkitem(item);
115  i->element = (void*) itm;
116  i->itemtype = ITEM;
117  return i;
118 }
119 
120 Item* insertsym(Item* item, Symbol* sym) /* insert a symbol before item */
121 /* a copy is not made because we need the same symbol in different lists */
122 {
123  Item* i;
124 
125  i = linkitem(item);
126  i->element = (void*) sym;
127  i->itemtype = SYMBOL;
128  return i;
129 }
130 
131 Item* linsertstr(List* list, const char* str) {
132  return insertstr(list->next, str);
133 }
134 
135 Item* lappendstr(List* list, const char* str) {
136  return insertstr(list, str);
137 }
138 
139 Item* linsertsym(List* list, Symbol* sym) {
140  return insertsym(list->next, sym);
141 }
142 
143 Item* lappendsym(List* list, Symbol* sym) {
144  return insertsym(list, sym);
145 }
146 
147 Item* lappenditem(List* list, Item* item) {
148  return insertitem(list, item);
149 }
150 
151 void remove(Item* item) {
152  assert(item->itemtype); /* can't delete list */
153  item->next->prev = item->prev;
154  item->prev->next = item->next;
155  free(item);
156 }
157 
158 static long mallocsize = 0;
159 static long mallocpieces = 0;
160 
161 char* emalloc(unsigned n) { /* check return from malloc */
162  char* p;
163 
164  p = static_cast<char*>(malloc(n));
165  if (p == (char*) 0) {
166  memory_usage();
167  diag("out of memory", (char*) 0);
168  }
169  mallocsize += n;
170  mallocpieces++;
171  return p;
172 }
173 
174 void memory_usage() {
175  Fprintf(stderr, "malloc'ed a total of %ld bytes in %ld pieces\n", mallocsize, mallocpieces);
176 }
177 
178 char* stralloc(const char* buf, char* rel) {
179  /* allocate space, copy buf, and free rel */
180  char* s;
181  s = (char*) emalloc((unsigned) (strlen(buf) + 1));
182  Strcpy(s, buf);
183  if (rel) {
184  free(rel);
185  }
186  return s;
187 }
188 
189 void deltokens(Item* q1, Item* q2) /* delete tokens from q1 to q2 */
190 {
191  /* It is a serious error if q2 precedes q1 */
192  Item* q;
193  for (q = q1; q != q2;) {
194  q = q->next;
195  remove(q->prev);
196  }
197  remove(q2);
198 }
199 
200 void move(Item* q1, Item* q2, Item* q3) /* move q1 to q2 and insert before q3*/
201 {
202  /* it is a serious error if q2 precedes q1 */
203  assert(q1 && q2);
204  assert(q1->itemtype && q2->itemtype);
205  q1->prev->next = q2->next; /* remove from first list */
206  q2->next->prev = q1->prev;
207 
208  q1->prev = q3->prev;
209  q3->prev->next = q1;
210  q3->prev = q2;
211  q2->next = q3;
212 }
213 
214 void movelist(Item* q1, Item* q2, List* s) /* move q1 to q2 from old list to end of list s*/
215 {
216  move(q1, q2, s);
217 }
218 
219 void replacstr(Item* q, const char* s) {
220  q->itemtype = STRING;
221  q->element = (void*) stralloc(s, (char*) 0);
222 }
223 
224 Item* putintoken(const char* s, short type, short toktype) { /* make sure a symbol exists for s and
225  append to intoken list */
226  Symbol* sym;
227  Item* q;
228  static int linenum = 0;
229 
230  if (debugtoken) {
231  Fprintf(stderr, "%s|", s);
232  }
233  if (s == (char*) 0)
234  diag("internal error", " in putintoken");
235  switch (type) {
236  case STRING:
237  case REAL:
238  case INTEGER:
239  q = insertstr(intoken, s);
240  q->itemsubtype = toktype;
241  return q;
242  case NEWLINE:
243  q = insertsym(intoken, SYM0);
244  q->itemtype = NEWLINE;
245  q->itemsubtype = ++linenum;
246  return q;
247  default:
248  if ((sym = lookup(s)) == SYM0) {
249  sym = install(s, type);
250  }
251  break;
252  }
253  q = insertsym(intoken, sym);
254  if (toktype) {
255  q->itemsubtype = toktype;
256  } else {
257  q->itemsubtype = sym->type;
258  }
259  return q;
260 }
261 
262 #include <stdarg.h>
263 
264 /* make a list of item pointers: notice that the items themselves remain
265 in whatever list they happen to be in. */
266 /* usage is q = makelist(n, q1, q2,..., qn); and q is of type LIST and
267  is not in any list */
268 
269 Item* makelist(int narg, ...) {
270  va_list ap;
271  int i;
272  List* l;
273  Item *ql, *q;
274 
275  l = newlist();
276  ql = newitem();
277  ql->itemtype = LIST;
278  ql->element = (void*) l;
279  va_start(ap, narg);
280  for (i = 0; i < narg; i++) {
281  q = va_arg(ap, Item*);
282  append(ql, q);
283  }
284  va_end(ap);
285 
286  return ql;
287 }
288 
289 void append(Item* ql, Item* q) {
290  assert(ql->itemtype == LIST);
291  IGNORE(insertitem((Item*) (LST(ql)), q));
292 }
293 
294 Item* prepend(Item* ql, Item* q) {
295  List* l;
296 
297  assert(ql->itemtype == LIST);
298  l = LST(ql);
299  IGNORE(insertitem((Item*) l->next, q));
300  return ql;
301 }
302 
303 /* An item which is an array of item pointers. Note where the size of
304 the array is held. */
305 
306 Item* itemarray(int narg, ...) {
307  va_list ap;
308  int i;
309  Item *ql, *q, **qa;
310 
311  ql = newitem();
312  va_start(ap, narg);
313  ql->itemtype = ITEMARRAY;
314  qa = (Item**) emalloc((unsigned) (narg + 1) * sizeof(Item*));
315  qa++;
316  ql->element = (void*) qa;
317  for (i = 0; i < narg; i++) {
318  q = va_arg(ap, Item*);
319  qa[i] = q;
320  }
321  va_end(ap);
322  ITMA(ql)[-1] = (Item*) ((size_t) narg);
323  return ql;
324 }
#define STRING
Definition: bbslsrv.cpp:9
#define i
Definition: md1redef.h:19
char buf[512]
Definition: init.cpp:13
List * intoken
Definition: init.cpp:12
#define assert(ex)
Definition: hocassrt.h:24
static int narg()
Definition: ivocvect.cpp:121
#define ITEMARRAY
Definition: model.h:94
#define SYM0
Definition: model.h:63
#define SYMBOL
Definition: model.h:91
#define ITEM
Definition: model.h:92
#define IGNORE(arg)
Definition: model.h:224
#define LST(q)
Definition: model.h:79
#define ITMA(q)
Definition: model.h:78
#define Strcpy
Definition: model.h:215
Symbol * lookup(const char *)
#define LIST
Definition: model.h:93
Symbol * install(const char *, int)
static int linenum
Definition: io.cpp:20
Item * prepend(Item *ql, Item *q)
Definition: list.cpp:294
void remove(Item *item)
Definition: list.cpp:151
char * stralloc(const char *buf, char *rel)
Definition: list.cpp:178
void movelist(Item *q1, Item *q2, List *s)
Definition: list.cpp:214
Item * prev(Item *item)
Definition: list.cpp:94
void freelist(List **plist)
Definition: list.cpp:58
static int debugtoken
Definition: list.cpp:41
Item * car(List *list)
Definition: list.cpp:83
void move(Item *q1, Item *q2, Item *q3)
Definition: list.cpp:200
Item * linsertstr(List *list, const char *str)
Definition: list.cpp:131
char * emalloc(unsigned n)
Definition: list.cpp:161
void replacstr(Item *q, const char *s)
Definition: list.cpp:219
Item * next(Item *item)
Definition: list.cpp:89
void deltokens(Item *q1, Item *q2)
Definition: list.cpp:189
List * newlist()
Definition: list.cpp:48
Item * putintoken(const char *s, short type, short toktype)
Definition: list.cpp:224
Item * makelist(int narg,...)
Definition: list.cpp:269
Item * itemarray(int narg,...)
Definition: list.cpp:306
static Item * linkitem(Item *item)
Definition: list.cpp:72
Item * lappenditem(List *list, Item *item)
Definition: list.cpp:147
static long mallocpieces
Definition: list.cpp:159
void memory_usage()
Definition: list.cpp:174
Item * insertsym(Item *item, Symbol *sym)
Definition: list.cpp:120
void append(Item *ql, Item *q)
Definition: list.cpp:289
static long mallocsize
Definition: list.cpp:158
Item * insertitem(Item *item, Item *itm)
Definition: list.cpp:110
Item * linsertsym(List *list, Symbol *sym)
Definition: list.cpp:139
Item * insertstr(Item *item, const char *str)
Definition: list.cpp:99
Item * lappendsym(List *list, Symbol *sym)
Definition: list.cpp:143
Item * lappendstr(List *list, const char *str)
Definition: list.cpp:135
static Item * newitem()
Definition: list.cpp:44
#define diag(s)
Definition: nonlin.cpp:19
int const size_t const size_t n
Definition: nrngsl.h:10
size_t q
size_t p
s
Definition: multisend.cpp:521
short type
Definition: cabvars.h:10
Definition: model.h:8
struct Item * prev
Definition: model.h:13
void * element
Definition: model.h:11
short itemtype
Definition: model.h:9
struct Item * next
Definition: model.h:12
Definition: model.h:47
short type
Definition: model.h:48
int Fprintf(FILE *stream, const char *fmt, Args... args)
Definition: logger.hpp:8