NEURON
list.cpp
Go to the documentation of this file.
1 #include <../../nmodlconf.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 "model.h"
34 #include "parse1.hpp"
35 
36 #define DEBUG 0
37 #if DEBUG
38 static int debugtoken=1;
39 #else
40 static int debugtoken=0;
41 #endif
42 
43 static Item *
45 {
46  return (Item *)emalloc(sizeof(Item));
47 }
48 
49 List *
51 {
52  Item *i;
53  i = newitem();
54  i->prev = i;
55  i->next = i;
56  i->element = (void *)0;
57  i->itemtype = 0;
58  return (List *)i;
59 }
60 
61 void freelist(List** plist) /*free the list but not the elements*/
62 {
63  Item *i1, *i2;
64  if (!(*plist)) {
65  return;
66  }
67  for (i1 = (*plist)->next; i1 != *plist; i1 = i2) {
68  i2 = i1->next;
69  Free(i1);
70  }
71  Free(*plist);
72  *plist = (List *)0;
73 }
74 
75 static Item *
76 linkitem(Item* item)
77 {
78  Item *i;
79 
80  i = newitem();
81  i->prev = item->prev;
82  i->next = item;
83  item->prev = i;
84  i->prev->next = i;
85  return i;
86 }
87 
88 Item *car(List* list)
89 {
90  Item *q = (Item *)list;
91  assert(q && q->itemtype == 0);
92  return next(q);
93 }
94 
95 Item *next(Item* item)
96 {
97  assert(item->next->itemtype); /* never return the list item */
98  return item->next;
99 }
100 
101 Item *prev(Item* item)
102 {
103  assert(item->prev->itemtype); /* never return the list item */
104  return item->prev;
105 }
106 
107 Item *
108 insertstr(Item* item, char* str) /* insert a copy of the string before item */
109 /* a copy is made because strings are often assembled into a reusable buffer*/
110 {
111  Item *i;
112 
113  i = linkitem(item);
114  i->element = (void *)stralloc(str, (char *)0);
115  i->itemtype = STRING;
116  return i;
117 }
118 
119 Item *
120 insertitem(Item* item, Item* itm) /* insert a item pointer before item */
121 {
122  Item *i;
123 
124  i = linkitem(item);
125  i->element = (void *)itm;
126  i->itemtype = ITEM;
127  return i;
128 }
129 
130 Item *
131 insertsym(Item* item, Symbol* sym) /* insert a symbol before item */
132 /* a copy is not made because we need the same symbol in different lists */
133 {
134  Item *i;
135 
136  i = linkitem(item);
137  i->element = (void *)sym;
138  i->itemtype = SYMBOL;
139  return i;
140 }
141 
142 Item *
143 linsertstr(List* list, char* str)
144 {
145  return insertstr(list->next, str);
146 }
147 
148 Item *
149 lappendstr(List* list, char* str)
150 {
151  return insertstr(list, str);
152 }
153 
154 Item *
155 linsertsym(List* list, Symbol* sym)
156 {
157  return insertsym(list->next, sym);
158 }
159 
160 Item *
161 lappendsym(List* list, Symbol* sym)
162 {
163  return insertsym(list, sym);
164 }
165 
166 Item *
167 lappenditem(List* list, Item* item)
168 {
169  return insertitem(list, item);
170 }
171 
172 void remove(Item* item)
173 {
174  assert(item->itemtype); /* can't delete list */
175  item->next->prev = item->prev;
176  item->prev->next = item->next;
177  Free(item);
178 }
179 
180 static long mallocsize=0;
181 static long mallocpieces=0;
182 
183 #if LINT
184 double *emalloc(unsigned n) { /* check return from malloc */
185  assert(0);
186  return (double *)0;
187 }
188 #else
189 char *emalloc(unsigned n) { /* check return from malloc */
190  char *p;
191 
192  p = static_cast<char*>(malloc(n));
193  if (p == (char *)0) {
194  memory_usage();
195  diag("out of memory", (char *)0);
196  }
197  mallocsize += n;
198  mallocpieces++;
199  return p;
200 }
201 #endif /*LINT*/
202 
203 void memory_usage() {
204  Fprintf(stderr, "malloc'ed a total of %ld bytes in %ld pieces\n",
206 }
207 
208 char *stralloc(char* buf, char* rel) {
209  /* allocate space, copy buf, and free rel */
210  char *s;
211  s = (char *)emalloc((unsigned)(strlen(buf) + 1));
212  Strcpy(s, buf);
213  if (rel) {
214  Free(rel);
215  }
216  return s;
217 }
218 
219 void deltokens(Item* q1, Item* q2) /* delete tokens from q1 to q2 */
220 {
221  /* It is a serious error if q2 precedes q1 */
222  Item *q;
223  for (q = q1; q != q2;) {
224  q = q->next;
225  remove(q->prev);
226  }
227  remove(q2);
228 
229 }
230 
231 void move(Item* q1, Item* q2, Item* q3) /* move q1 to q2 and insert before q3*/
232 {
233  /* it is a serious error if q2 precedes q1 */
234  assert(q1 && q2);
235  assert(q1->itemtype && q2->itemtype);
236  q1->prev->next = q2->next; /* remove from first list */
237  q2->next->prev = q1->prev;
238 
239  q1->prev = q3->prev;
240  q3->prev->next = q1;
241  q3->prev = q2;
242  q2->next = q3;
243 }
244 
245 void movelist(Item* q1, Item* q2, List* s) /* move q1 to q2 from old list to end of list s*/
246 {
247  move(q1, q2, s);
248 }
249 
250 void replacstr(Item* q, char* s)
251 {
252  q->itemtype = STRING;
253  q->element = (void *)stralloc(s, (char *)0);
254 
255 }
256 
257 Item *
258 putintoken(char* s, short type, short toktype)
259 { /* make sure a symbol exists for s and
260  append to intoken list */
261  Symbol *sym;
262  Item *q;
263  static int linenum=0;
264 
265  if (debugtoken) {
266  Fprintf(stderr, "%s|", s);
267  }
268  if (s == (char *)0)
269  diag("internal error", " in putintoken");
270  switch (type) {
271 
272  case STRING:
273  case REAL:
274  case INTEGER:
275  q = insertstr(intoken, s);
276  q->itemsubtype = toktype;
277  return q;
278  case NEWLINE:
279  q = insertsym(intoken, SYM0);
280  q->itemtype = NEWLINE;
281  q->itemsubtype = ++linenum;
282  return q;
283  default:
284  if ((sym = lookup(s)) == SYM0) {
285  sym = install(s, type);
286  }
287  break;
288  }
289  q = insertsym(intoken, sym);
290  if (toktype) {
291  q->itemsubtype = toktype;
292  }else{
293  q->itemsubtype = sym->type;
294  }
295  return q;
296 }
297 
298 #if MAC || defined(__TURBOC__)
299 #undef HAVE_STDARG_H
300 #define HAVE_STDARG_H 1
301 #endif
302 
303 #if HAVE_STDARG_H
304 #include <stdarg.h>
305 #else
306 #include <varargs.h>
307 #endif
308 
309 /* make a list of item pointers: notice that the items themselves remain
310 in whatever list they happen to be in. */
311 /* usage is q = makelist(n, q1, q2,..., qn); and q is of type LIST and
312  is not in any list */
313 
314 Item *
315 #if HAVE_STDARG_H
316 makelist(int narg, ...)
317 {
318 #else
319 makelist(va_alist)
320  va_dcl
321 {
322  int narg;
323 #endif
324  va_list ap;
325  int i;
326  List *l;
327  Item *ql,*q;
328 
329  l = newlist();
330  ql = newitem();
331  ql->itemtype = LIST;
332  ql->element = (void *)l;
333 #if HAVE_STDARG_H
334  va_start (ap, narg);
335 #else
336  va_start (ap);
337  narg = va_arg(ap, int);
338 #endif
339  for (i=0; i<narg; i++) {
340  q = va_arg(ap, Item *);
341  append(ql, q);
342  }
343  va_end (ap);
344 
345  return ql;
346 }
347 
348 void append(Item* ql, Item* q)
349 {
350  assert(ql->itemtype == LIST);
351  IGNORE(insertitem((Item *)(LST(ql)), q));
352 }
353 
354 Item *
356 {
357  List *l;
358 
359  assert(ql->itemtype == LIST);
360  l = LST(ql);
361  IGNORE(insertitem((Item *)l->next, q));
362  return ql;
363 }
364 
365 /* An item which is an array of item pointers. Note where the size of
366 the array is held. */
367 
368 Item *
369 #if HAVE_STDARG_H
370 itemarray(int narg, ...) {
371 #else
372 itemarray(va_alist)
373  va_dcl
374 {
375  int narg;
376 #endif
377  va_list ap;
378  int i;
379  Item *ql,*q, **qa;
380 
381  ql = newitem();
382 #if HAVE_STDARG_H
383  va_start (ap, narg);
384 #else
385  va_start (ap);
386  narg = va_arg(ap, int);
387 #endif
388  ql->itemtype = ITEMARRAY;
389  qa = (Item **)emalloc((unsigned)(narg + 1)*sizeof(Item *));
390  qa++;
391  ql->element = (void *)qa;
392  for (i=0; i<narg; i++) {
393  q = va_arg(ap, Item *);
394  qa[i] = q;
395  }
396  va_end (ap);
397  ITMA(ql)[-1] = (Item *)((size_t)narg);
398  return ql;
399 }
short itemsubtype
Definition: model.h:17
void deltokens(Item *q1, Item *q2)
Definition: list.cpp:219
char * stralloc(char *buf, char *rel)
Definition: list.cpp:208
short itemtype
Definition: model.h:16
#define ITEMARRAY
Definition: model.h:105
#define assert(ex)
Definition: hocassrt.h:26
static long mallocsize
Definition: list.cpp:180
short type
Definition: cabvars.h:10
Item * car(List *list)
Definition: list.cpp:88
short type
Definition: model.h:58
#define diag(s)
Definition: fmenu.cpp:188
size_t p
Item * lappendsym(List *list, Symbol *sym)
Definition: list.cpp:161
#define REAL
Definition: machine.h:191
static int debugtoken
Definition: list.cpp:40
struct Item * prev
Definition: model.h:20
static int narg()
Definition: ivocvect.cpp:135
#define Fprintf
Definition: model.h:249
Item * next(Item *item)
Definition: list.cpp:95
#define LIST
Definition: model.h:104
#define SYMBOL
Definition: model.h:102
struct Item * next
Definition: model.h:19
static Item * linkitem(Item *item)
Definition: list.cpp:76
#define IGNORE(arg)
Definition: model.h:262
Definition: model.h:15
Item * insertsym(Item *item, Symbol *sym)
Definition: list.cpp:131
Item * itemarray(va_alist) va_dcl
Definition: list.cpp:372
Item * prev(Item *item)
Definition: list.cpp:101
void append(Item *ql, Item *q)
Definition: list.cpp:348
#define install
Definition: redef.h:82
int const size_t const size_t n
Definition: nrngsl.h:12
#define Free
Definition: list.cpp:38
void movelist(Item *q1, Item *q2, List *s)
Definition: list.cpp:245
_CONST char * s
Definition: system.cpp:74
Item * lappendstr(List *list, char *str)
Definition: list.cpp:149
Item * insertitem(Item *item, Item *itm)
Definition: list.cpp:120
static int linenum
Definition: io.cpp:22
Item * makelist(va_alist) va_dcl
Definition: list.cpp:319
#define STRING
Definition: bbslsrv.cpp:9
#define ITEM
Definition: model.h:103
Item * linsertstr(List *list, char *str)
Definition: list.cpp:143
static long mallocpieces
Definition: list.cpp:181
Definition: model.h:57
#define LST(q)
Definition: model.h:90
char * emalloc(unsigned n)
Definition: list.cpp:189
void * element
Definition: model.h:18
List * newlist()
Definition: list.cpp:50
#define Strcpy
Definition: model.h:253
#define lookup
Definition: redef.h:90
Item * lappenditem(List *list, Item *item)
Definition: list.cpp:167
Item * linsertsym(List *list, Symbol *sym)
Definition: list.cpp:155
void memory_usage()
Definition: list.cpp:203
Item * insertstr(Item *item, char *str)
Definition: list.cpp:108
List * intoken
Definition: init.cpp:12
void freelist(List **plist)
Definition: list.cpp:61
void move(Item *q1, Item *q2, Item *q3)
Definition: list.cpp:231
#define i
Definition: md1redef.h:12
static Item * newitem()
Definition: list.cpp:44
Item * prepend(Item *ql, Item *q)
Definition: list.cpp:355
char buf[512]
Definition: init.cpp:13
Item * putintoken(char *s, short type, short toktype)
Definition: list.cpp:258
void replacstr(Item *q, char *s)
Definition: list.cpp:250
#define SYM0
Definition: model.h:74
size_t q
#define ITMA(q)
Definition: model.h:89