1/*	Id: misc.c,v 1.17 2009/02/11 15:58:55 ragge Exp 	*/
2/*	$NetBSD$	*/
3/*
4 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code and documentation must retain the above
11 * copyright notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * 	This product includes software developed or owned by Caldera
18 *	International, Inc.
19 * Neither the name of Caldera International, Inc. nor the names of other
20 * contributors may be used to endorse or promote products derived from
21 * this software without specific prior written permission.
22 *
23 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
28 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
32 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <string.h>
38
39#include "defines.h"
40#include "defs.h"
41
42int max(int, int);
43
44void
45cpn(n, a, b)
46register int n;
47register char *a, *b;
48{
49while(--n >= 0)
50	*b++ = *a++;
51}
52
53
54int
55eqn(n, a, b)
56register int n;
57register char *a, *b;
58{
59while(--n >= 0)
60	if(*a++ != *b++)
61		return(NO);
62return(YES);
63}
64
65
66
67
68
69
70int
71cmpstr(a, b, la, lb)	/* compare two strings */
72register char *a, *b;
73ftnint la, lb;
74{
75register char *aend, *bend;
76aend = a + la;
77bend = b + lb;
78
79
80if(la <= lb)
81	{
82	while(a < aend)
83		if(*a != *b)
84			return( *a - *b );
85		else
86			{ ++a; ++b; }
87
88	while(b < bend)
89		if(*b != ' ')
90			return(' ' - *b);
91		else
92			++b;
93	}
94
95else
96	{
97	while(b < bend)
98		if(*a != *b)
99			return( *a - *b );
100		else
101			{ ++a; ++b; }
102	while(a < aend)
103		if(*a != ' ')
104			return(*a - ' ');
105		else
106			++a;
107	}
108return(0);
109}
110
111
112
113
114
115chainp hookup(x,y)
116register chainp x, y;
117{
118register chainp p;
119
120if(x == NULL)
121	return(y);
122
123for(p = x ; p->chain.nextp ; p = p->chain.nextp)
124	;
125p->chain.nextp = y;
126return(x);
127}
128
129
130
131struct bigblock *mklist(p)
132chainp p;
133{
134register struct bigblock *q;
135
136q = BALLO();
137q->tag = TLIST;
138q->b_list.listp = p;
139return(q);
140}
141
142
143chainp
144mkchain(bigptr p, chainp q)
145{
146	chainp r;
147
148	if(chains) {
149		r = chains;
150		chains = chains->chain.nextp;
151	} else
152		r = ALLOC(chain);
153
154	r->chain.datap = p;
155	r->chain.nextp = q;
156	return(r);
157}
158
159
160
161char * varstr(n, s)
162register int n;
163register char *s;
164{
165register int i;
166static char name[XL+1];
167
168for(i=0;  i<n && *s!=' ' && *s!='\0' ; ++i)
169	name[i] = *s++;
170
171name[i] = '\0';
172
173return( name );
174}
175
176
177
178
179char * varunder(n, s)
180register int n;
181register char *s;
182{
183register int i;
184static char name[XL+1];
185
186for(i=0;  i<n && *s!=' ' && *s!='\0' ; ++i)
187	name[i] = *s++;
188
189name[i] = '\0';
190
191return( name );
192}
193
194
195
196
197
198char * nounder(n, s)
199register int n;
200register char *s;
201{
202register int i;
203static char name[XL+1];
204
205for(i=0;  i<n && *s!=' ' && *s!='\0' ; ++s)
206	if(*s != '_')
207		name[i++] = *s;
208
209name[i] = '\0';
210
211return( name );
212}
213
214/*
215 * Save a block on heap.
216 */
217char *
218copyn(int n, char *s)
219{
220	char *p, *q;
221
222	p = q = ckalloc(n);
223	while(--n >= 0)
224		*q++ = *s++;
225	return(p);
226}
227
228/*
229 * Save a string on heap.
230 */
231char *
232copys(char *s)
233{
234	return(copyn(strlen(s)+1 , s));
235}
236
237/*
238 * convert a string to an int.
239 */
240ftnint
241convci(int n, char *s)
242{
243	ftnint sum;
244	sum = 0;
245	while(n-- > 0)
246		sum = 10*sum + (*s++ - '0');
247	return(sum);
248}
249
250char *convic(n)
251ftnint n;
252{
253static char s[20];
254register char *t;
255
256s[19] = '\0';
257t = s+19;
258
259do	{
260	*--t = '0' + n%10;
261	n /= 10;
262	} while(n > 0);
263
264return(t);
265}
266
267
268
269double convcd(n, s)
270int n;
271register char *s;
272{
273char v[100];
274register char *t;
275if(n > 90)
276	{
277	err("too many digits in floating constant");
278	n = 90;
279	}
280for(t = v ; n-- > 0 ; s++)
281	*t++ = (*s=='d' ? 'e' : *s);
282*t = '\0';
283return( atof(v) );
284}
285
286
287
288struct bigblock *mkname(l, s)
289int l;
290register char *s;
291{
292struct hashentry *hp;
293int hash;
294register struct bigblock *q;
295register int i;
296char n[VL];
297
298hash = 0;
299for(i = 0 ; i<l && *s!='\0' ; ++i)
300	{
301	hash += *s;
302	n[i] = *s++;
303	}
304hash %= MAXHASH;
305while( i < VL )
306	n[i++] = ' ';
307
308hp = hashtab + hash;
309while((q = hp->varp))
310	if( hash==hp->hashval && eqn(VL,n,q->b_name.varname) )
311		return(q);
312	else if(++hp >= lasthash)
313		hp = hashtab;
314
315if(++nintnames >= MAXHASH-1)
316	fatal("hash table full");
317hp->varp = q = BALLO();
318hp->hashval = hash;
319q->tag = TNAME;
320cpn(VL, n, q->b_name.varname);
321return(q);
322}
323
324
325
326struct labelblock *mklabel(l)
327ftnint l;
328{
329register struct labelblock *lp;
330
331if(l == 0)
332	return(0);
333
334for(lp = labeltab ; lp < highlabtab ; ++lp)
335	if(lp->stateno == l)
336		return(lp);
337
338if(++highlabtab >= labtabend)
339	fatal("too many statement numbers");
340
341lp->stateno = l;
342lp->labelno = newlabel();
343lp->blklevel = 0;
344lp->labused = NO;
345lp->labdefined = NO;
346lp->labinacc = NO;
347lp->labtype = LABUNKNOWN;
348return(lp);
349}
350
351int
352newlabel()
353{
354return( lastlabno++ );
355}
356
357
358/* find or put a name in the external symbol table */
359
360struct extsym *mkext(s)
361char *s;
362{
363int i;
364register char *t;
365char n[XL];
366struct extsym *p;
367
368i = 0;
369t = n;
370while(i<XL && *s)
371	*t++ = *s++;
372while(t < n+XL)
373	*t++ = ' ';
374
375for(p = extsymtab ; p<nextext ; ++p)
376	if(eqn(XL, n, p->extname))
377		return( p );
378
379if(nextext >= lastext)
380	fatal("too many external symbols");
381
382cpn(XL, n, nextext->extname);
383nextext->extstg = STGUNKNOWN;
384nextext->extsave = NO;
385nextext->extp = 0;
386nextext->extleng = 0;
387nextext->maxleng = 0;
388nextext->extinit = NO;
389return( nextext++ );
390}
391
392
393
394
395
396
397
398
399struct bigblock *builtin(t, s)
400int t;
401char *s;
402{
403register struct extsym *p;
404register struct bigblock *q;
405
406p = mkext(s);
407if(p->extstg == STGUNKNOWN)
408	p->extstg = STGEXT;
409else if(p->extstg != STGEXT)
410	{
411	err1("improper use of builtin %s", s);
412	return(0);
413	}
414
415q = BALLO();
416q->tag = TADDR;
417q->vtype = t;
418q->vclass = CLPROC;
419q->vstg = STGEXT;
420q->b_addr.memno = p - extsymtab;
421return(q);
422}
423
424
425void
426frchain(p)
427register chainp *p;
428{
429register chainp q;
430
431if(p==0 || *p==0)
432	return;
433
434for(q = *p; q->chain.nextp ; q = q->chain.nextp)
435	;
436q->chain.nextp = chains;
437chains = *p;
438*p = 0;
439}
440
441
442ptr cpblock(n,p)
443register int n;
444register void * p;
445{
446register char *q, *r = p;
447ptr q0;
448
449q = q0 = ckalloc(n);
450while(n-- > 0)
451	*q++ = *r++;
452return(q0);
453}
454
455
456int
457max(a,b)
458int a,b;
459{
460return( a>b ? a : b);
461}
462
463
464ftnint lmax(a, b)
465ftnint a, b;
466{
467return( a>b ? a : b);
468}
469
470ftnint lmin(a, b)
471ftnint a, b;
472{
473return(a < b ? a : b);
474}
475
476
477
478int
479maxtype(t1, t2)
480int t1, t2;
481{
482int t;
483
484t = max(t1, t2);
485if(t==TYCOMPLEX && (t1==TYDREAL || t2==TYDREAL) )
486	t = TYDCOMPLEX;
487return(t);
488}
489
490
491
492/* return log base 2 of n if n a power of 2; otherwise -1 */
493int
494flog2(n)
495ftnint n;
496{
497int k;
498
499/* trick based on binary representation */
500
501if(n<=0 || (n & (n-1))!=0)
502	return(-1);
503
504for(k = 0 ;  n >>= 1  ; ++k)
505	;
506return(k);
507}
508
509
510void
511frrpl()
512{
513chainp rp;
514
515while(rpllist)
516	{
517	rp = rpllist->rplblock.nextp;
518	ckfree(rpllist);
519	rpllist = rp;
520	}
521}
522
523void
524popstack(p)
525register chainp *p;
526{
527register chainp q;
528
529if(p==NULL || *p==NULL)
530	fatal("popstack: stack empty");
531q = (*p)->chain.nextp;
532ckfree(*p);
533*p = q;
534}
535
536
537
538struct bigblock *
539callk(type, name, args)
540int type;
541char *name;
542bigptr args;
543{
544register struct bigblock *p;
545
546p = mkexpr(OPCALL, builtin(type,name), args);
547p->vtype = type;
548return(p);
549}
550
551
552
553struct bigblock *
554call4(type, name, arg1, arg2, arg3, arg4)
555int type;
556char *name;
557bigptr arg1, arg2, arg3, arg4;
558{
559struct bigblock *args;
560args = mklist( mkchain(arg1, mkchain(arg2, mkchain(arg3, mkchain(arg4, NULL)) ) ) );
561return( callk(type, name, args) );
562}
563
564
565
566
567struct bigblock *call3(type, name, arg1, arg2, arg3)
568int type;
569char *name;
570bigptr arg1, arg2, arg3;
571{
572struct bigblock *args;
573args = mklist( mkchain(arg1, mkchain(arg2, mkchain(arg3, NULL) ) ) );
574return( callk(type, name, args) );
575}
576
577
578
579
580
581struct bigblock *
582call2(type, name, arg1, arg2)
583int type;
584char *name;
585bigptr arg1, arg2;
586{
587bigptr args;
588
589args = mklist( mkchain(arg1, mkchain(arg2, NULL) ) );
590return( callk(type,name, args) );
591}
592
593
594
595
596struct bigblock *call1(type, name, arg)
597int type;
598char *name;
599bigptr arg;
600{
601return( callk(type,name, mklist(mkchain(arg,0)) ));
602}
603
604
605struct bigblock *call0(type, name)
606int type;
607char *name;
608{
609return( callk(type, name, NULL) );
610}
611
612
613
614struct bigblock *
615mkiodo(dospec, list)
616chainp dospec, list;
617{
618register struct bigblock *q;
619
620q = BALLO();
621q->tag = TIMPLDO;
622q->b_impldo.varnp = (struct bigblock *)dospec;
623q->b_impldo.datalist = list;
624return(q);
625}
626
627
628
629
630ptr
631ckalloc(int n)
632{
633	ptr p;
634
635	if ((p = calloc(1, (unsigned) n)) == NULL)
636		fatal("out of memory");
637#ifdef PCC_DEBUG
638	if (mflag)
639		printf("ckalloc: sz %d ptr %p\n", n, p);
640#endif
641	return(p);
642}
643
644void
645ckfree(void *p)
646{
647#ifdef PCC_DEBUG
648	if (mflag)
649		printf("ckfree: ptr %p\n", p);
650#endif
651	free(p);
652}
653
654#if 0
655int
656isaddr(p)
657register bigptr p;
658{
659if(p->tag == TADDR)
660	return(YES);
661if(p->tag == TEXPR)
662	switch(p->b_expr.opcode)
663		{
664		case OPCOMMA:
665			return( isaddr(p->b_expr.rightp) );
666
667		case OPASSIGN:
668		case OPPLUSEQ:
669			return( isaddr(p->b_expr.leftp) );
670		}
671return(NO);
672}
673#endif
674
675/*
676 * Return YES if not an expression.
677 */
678int
679addressable(bigptr p)
680{
681	switch(p->tag) {
682	case TCONST:
683		return(YES);
684
685	case TADDR:
686		return( addressable(p->b_addr.memoffset) );
687
688	default:
689		return(NO);
690	}
691}
692
693
694int
695hextoi(c)
696register int c;
697{
698register char *p;
699static char p0[17] = "0123456789abcdef";
700
701for(p = p0 ; *p ; ++p)
702	if(*p == c)
703		return( p-p0 );
704return(16);
705}
706