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