aboutsummaryrefslogtreecommitdiff
path: root/pkg/utilities/nttools/stxtools/vexstack.x
blob: 8f51b2bb8adea0c80fdd94ecef0a04e752e54e26 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
include "vex.h"

# VEX_STACK -- Procedures which manipulate the vex stack
#
# The expression evaluator, vex_eval, uses a stack to hold intermediate
# results, constants, and variable names in the expression. There are
# actually two stacks, a type stack wich contains the data types of the
# elements on the stack, and a value stack, which contains pointers to
# the stack elements. Constants and variable names are stored in two
# buffers which are part of the stack structure and pointers to their
# locations are placed on the stack. Intermediate results are stored in 
# malloc'ed arrays and their pointers are also placed on the stack. The
# stack structure contains three indices, bottom, an index one greater
# than the last constant or variable name, top, an index that is one 
# greater than the current top of stack, and high, an index that is one 
# greater than the last valid pointer on the stack. Valid pointers exist
# beyond the top of stack because the arrays which store intermediate 
# results are not mfree'd when the stack is popped, instead, they are 
# kept in case they may be needed for a future intermediate result. The 
# only user callable procedure in this file is stk_alloc, which should 
# be called by getvar, the user's function which fills an array when
# passed the name of a variable.
#
# B.Simon	24-Apr-91	Original
# B.Simon	15-Oct-98	Store strings in pseudocode, not on stack

# STK_ALLOC -- Allocate an array of the specified length and type

pointer procedure stk_alloc (stack, len, type)

pointer	stack		# i: Stack structure
int	len		# i: Length of array to allocate
int	type		# i: Data type of array (spp type)
#--
int	index, stype, top
pointer	var, svar

string	badstack  "stk_alloc: illegal type on stack"
string	badsize   "Requested array size does not match previous requests"

errchk	stk_find

begin
	# Check to see if array length is being defined for the first time

	if (STK_LENVAL(stack) == 0 && len != 0) {

	    # Store length in stack structure

	    STK_LENVAL(stack) = len

	    # Free all stack arrays not currently being used

	    index = STK_TOP(stack)
	    while (index < STK_HIGH(stack)) {
		svar = STK_VALUE(stack,index)
		stype = STK_TYPE(stack,index)
		call mfree (svar, stype)
		index = index + 1
	    }
	    STK_HIGH(stack) = STK_TOP(stack)

	    # Reallocate the null buffer

	    if (STK_NULLARY(stack) != NULL) {
		call stk_freenull (stack)
		call stk_initnull (stack, true)
	    }

	    # Convert length one arrays to their full length

	    index = 0
	    while (index < STK_TOP(stack)) {
	        svar = STK_VALUE(stack,index)
		stype = STK_TYPE(stack,index)

		call malloc (var, len, stype)
		STK_VALUE(stack,index) = var
		switch (stype) {
		case TY_INT,TY_LONG:
		    call amovki (Memi[svar], Memi[var], len)
		    call mfree (svar, TY_INT)
		case TY_REAL:
		    call amovkr (Memr[svar], Memr[var], len)
		    call mfree (svar, TY_REAL)
		case TY_DOUBLE:
		    call amovkd (Memd[svar], Memd[var], len)
		    call mfree (svar, TY_DOUBLE)
		default:
		    call error (1, badstack)
		}		
		index = index + 1
	    }
	}

	# Check requested size

	if (len != 0 && len != STK_LENVAL(stack))
	    call error (1, badsize)

	# Look for an existing array of the same type

	call stk_find (stack, type, index)

	# Increment top of stack pointer

	top = STK_TOP(stack)
	STK_TOP(stack) = top + 1

	# Swap array with one currently at top of stack

	if (top != index) {
	    stype = STK_TYPE(stack,top)
	    STK_TYPE(stack,top) = STK_TYPE(stack,index)
	    STK_TYPE(stack,index) = stype

	    svar = STK_VALUE(stack,top)
	    STK_VALUE(stack,top) = STK_VALUE(stack,index)
	    STK_VALUE(stack,index) = svar
	}

	var = STK_VALUE(stack,top)
	return (var)
end

# STK_CLEAR -- Clear all stack elements above the bottom

procedure stk_clear (stack)

pointer	stack		# u: Stack pointer
#--
int	index

begin
	# Free all value arrays above the bottom of stack

	index = 0
	while (index < STK_HIGH(stack)) {
	    call mfree (STK_VALUE(stack,index), STK_TYPE(stack,index))
	    index = index + 1
	}

	# Free null array

	call stk_freenull (stack)

	# Reset scalars

	STK_TOP(stack) = 0
	STK_HIGH(stack) = 0
	STK_LENVAL(stack) = 0
end

# STK_COERCE -- Coerce an array in the stack to the specified type

procedure stk_coerce (stack, pos, type, var)

pointer	stack		# i: Stack descriptor
int	pos		# i: Position of array in stack
int	type		# i: New type for array
pointer	var		# o: New pointer to array
#--
int	index, last, stype, len, i
pointer	svar

string	underflow  "stk_coerce: underflow in expression evaluator"

errchk	stk_find

begin
	# Convert relative to absolute position

	if (pos == TOP) {
	    index = STK_TOP(stack) - 1
	    if (index < 0)
		call error (1, underflow)
	} else {
	    index = pos
	}

	# If type of array matches requested type, return pointer to array
	# Otherwise, get new array and copy old array to it

	if (type == STK_TYPE(stack,index)) {
	    var = STK_VALUE(stack,index)

	} else {
	    # Find array of correct type

	    last = index
	    call stk_find (stack, type, index)

	    # Copy array, converting to new type

	    len = max (1, STK_LENVAL(stack))
	    var = STK_VALUE(stack,index)

	    stype = STK_TYPE(stack,last)
	    svar = STK_VALUE(stack,last)

	    switch (type) {
	    case TY_INT,TY_LONG:
		switch (stype) {
		case TY_INT,TY_LONG:
		    ; # can't happen
		case TY_REAL:
		    do i = 0, len-1 {
			if (IS_INDEFR(Memr[svar+i])) {
			    Memi[var+i] = INDEFI
			} else {
			    Memi[var+i] = Memr[svar+i]
			}
		    }
		case TY_DOUBLE:
		    do i = 0, len-1 {
			if (IS_INDEFD(Memd[svar+i])) {
			    Memi[var+i] = INDEFI
			} else {
			    Memi[var+i] = Memd[svar+i]
			}
		    }
		}
	    case TY_REAL:
		switch (stype) {
		case TY_INT,TY_LONG:
		    do i = 0, len-1 {
			if (IS_INDEFI(Memi[svar+i])) {
			    Memr[var+i] = INDEFR
			} else {
			    Memr[var+i] = Memi[svar+i]
			}
		    }
		case TY_REAL:
		    ; # can't happen
		case TY_DOUBLE:
		    do i = 0, len-1 {
			if (IS_INDEFD(Memd[svar+i])) {
			    Memr[var+i] = INDEFR
			} else {
			    Memr[var+i] = Memd[svar+i]
			}
		    }
		}
	    case TY_DOUBLE:
		switch (stype) {
		case TY_INT,TY_LONG:
		    do i = 0, len-1 {
			if (IS_INDEFI(Memi[svar+i])) {
			    Memd[var+i] = INDEFD
			} else {
			    Memd[var+i] = Memi[svar+i]
			}
		    }
		case TY_REAL:
		    do i = 0, len-1 {
			if (IS_INDEFR(Memr[svar+i])) {
			    Memd[var+i] = INDEFD
			} else {
			    Memd[var+i] = Memr[svar+i]
			}
		    }
		case TY_DOUBLE:
		    ; # can't happen
		}
	    }

	    # Swap position of new and old arrays on stack

	    STK_TYPE(stack,last) = STK_TYPE(stack,index)
	    STK_TYPE(stack,index) = stype

	    STK_VALUE(stack,last) = STK_VALUE(stack,index)
	    STK_VALUE(stack,index) = svar
	}
	
end

# STK_FETCH -- Fetch the specified number of arrays from the stack

procedure stk_fetch (stack, nvar, var, len, type)

pointer	stack		# i: Stack descriptor
int	nvar		# i: Number of pointers requested
pointer	var[ARB]	# o: Array pointers
int	len		# o: Length of arrays
int	type		# o: Type of arrays
#--
int	one, two, index, ivar

string	underflow  "stk_fetch: underflow in expression evaluator"

errchk	stk_coerce

begin
	# If length is not yet defined, STK_LENVAL equals zero

	len = STK_LENVAL(stack)

	# Find the highest type in the pointers to be returned

	one = STK_TOP(stack) - 1
	two = STK_TOP(stack) - 2

	type = STK_TYPE(stack,one)
	if (nvar > 1) {
	    switch (STK_TYPE(stack,two)) {
	    case TY_INT, TY_LONG:
		;
	    case TY_REAL:
		if (type == TY_INT)
		    type = TY_REAL
	    case TY_DOUBLE:
		type = TY_DOUBLE
	    }
	}

	# Retrieve pointers to arrays from stack. var[nvar] is top of stack
	# Convert arrays to output type when the type differs

	index = STK_TOP(stack) - nvar
	do ivar = 1, nvar {
	    if (index < 0)
		call error (1, underflow)

	    if (type == STK_TYPE(stack,index) || index < two) {
		var[ivar] = STK_VALUE(stack,index)
	    } else {
	        call stk_coerce (stack, index, type, var[ivar])
	    }
	    index = index + 1
	}

end

# STK_FIND -- Find a free array of the proper type on the stack

procedure stk_find (stack, type, index)

pointer	stack		# i: Stack descriptor
int	type		# i: Required type
int	index		# o: Position on the stack
#--
int	len
pointer	var

string	overflow  "Expression too complex to be evaluated"

begin
	# Try to find an array of the proper type already on the stack

	index = STK_TOP(stack)
	while (index < STK_HIGH(stack)) {
	    if (type == STK_TYPE(stack,index))
		break

	    index = index + 1
	}

	# If not found, allocate a new array

	if (index == MAX_STACK) {
	    call error (1, overflow)

	} else if (index == STK_HIGH(stack)) {
	    len = max (1, STK_LENVAL(stack))
	    call malloc (var, len, type)

	    STK_TYPE(stack,index) = type
	    STK_VALUE(stack,index) = var
	    STK_HIGH(stack) = STK_HIGH(stack) + 1
	}

end

# STK_FREE -- Free memory used by the stack

procedure stk_free (stack)

pointer	stack		# u: Stack pointer
#--

begin
	# Free all values above the stack bottom

	call stk_clear (stack)

	# Free substructures in stack

	if (STK_NULLARY(stack) != NULL)
	    call mfree (STK_NULLARY(stack), TY_BOOL)

	call mfree (STK_VALARY(stack), TY_INT)
	call mfree (STK_TYPARY(stack), TY_INT)

	# Free the stack structure
	call mfree (stack, TY_INT)
end

# STK_FREENULL -- Free the null array in the stack

procedure stk_freenull (stack)

pointer	stack		# u: Stack structure
#--

begin
	if (STK_NULLARY(stack) != NULL)
	    call mfree (STK_NULLARY(stack), TY_BOOL)

	STK_NULLARY(stack) = NULL
end

# STK_GET -- Get a single array from the stack

procedure stk_get (stack, pos, var, len, type)

pointer	stack		# i: Stack descriptor
int	pos		# i: Position on the stack
pointer	var		# o: Pointer to array
int	len		# o: Length of array
int	type		# o: Type of the array
#--
int	index

string	underflow  "stk_get: underflow in expression evaluator"

begin
	# Convert relative to absolute position

	if (pos == TOP) {
	    index = STK_TOP(stack) - 1
	    if (index < 0)
		call error (1, underflow)
	} else {
	    index = pos
	}

	var = STK_VALUE(stack,index)
	len = STK_LENVAL(stack)
	type = STK_TYPE(stack,index)
end

# STK_GETNULL -- Get the null array from the stack

procedure stk_getnull (stack, nullvec)

pointer	stack		# i: Stack structure
pointer nullvec		# o: Null array
#--

begin
	nullvec = STK_NULLARY(stack)
end

# STK_INIT -- Initialize the stack

procedure stk_init (stack)

pointer	stack		# o: Stack pointer
#--

begin
	# Allocate stack and initialize members to zero

	call calloc (stack, SZ_STKSTRUCT, TY_INT)

	# Allocate substructures in stack

	call malloc (STK_VALARY(stack), MAX_STACK, TY_INT)
	call malloc (STK_TYPARY(stack), MAX_STACK, TY_INT)

end

# STK_INITNULL -- Initialize the null array on the stack

procedure stk_initnull (stack, value)

pointer	stack		# u: Stack structure
bool	value		# i: Value used in initialization
#--
int	len, i
pointer	nullvec

begin
	# Only initialize if array doesn't exist

	if (STK_NULLARY(stack) == NULL) {
	    len = STK_LENVAL(stack)

	    # Allocate array
	    call malloc (nullvec, len, TY_BOOL)
	    STK_NULLARY(stack) = nullvec

	    # Initialize to value
	    do i = 0, len-1
		Memb[nullvec+i] = value
	}

end

# STK_ORNULL -- Update null array by doing a logical or

procedure stk_ornull (stack, newvec, newlen)

pointer	stack		# u: Stack structure
bool	newvec[ARB]	# i: Array of new values
int	newlen		# i: Length of new array 
#--
int	len, i
pointer	nullvec

string	badlength  "stk_ornull: length of array does not match null array"

begin
	len = STK_LENVAL(stack)
	if (len != newlen)
	    call error (1, badlength)

	call stk_initnull (stack, false)
	nullvec = STK_NULLARY(stack)

	do i = 1, len {
	    Memb[nullvec] = Memb[nullvec] || newvec[i]
	    nullvec = nullvec + 1
	}

end

# STK_POP -- Remove the specified number of arrays from the stack

procedure stk_pop (stack, npop)

pointer	stack		# u: Stack structure
int	npop		# i: Number of arrays to pop
#--
int	top, index, type
pointer	var

string	underflow  "stk_pop: underflow in expression evaluator"

begin

	top = STK_TOP(stack) - 1
	index = top - npop

	if (index < 0) {
	    call error (1, underflow)
	} else {
	    STK_TOP(stack) = index + 1
	}

	var = STK_VALUE(stack,index)
	STK_VALUE(stack,index) = STK_VALUE(stack,top)
	STK_VALUE(stack,top) = var

	type = STK_TYPE(stack,index)
	STK_TYPE(stack,index) = STK_TYPE(stack,top)
	STK_TYPE(stack,top) = type

end

# STK_POS -- Compute absolute position on stack

int procedure stk_pos (stack, pos)

pointer	stack		# i: Stack structure
int	pos		# i: Position relative to top of stack
#--

begin
	return (STK_TOP(stack) - pos)
end

# STK_SETNULL -- Set a single value in the null array to true

procedure stk_setnull (stack, index)

pointer	stack		# u: Stack structure
int	index		# i: Index into null array
#--

begin
	STK_NULL(stack,index) = true
end