xref: /original-bsd/old/as.vax/asscan4.c (revision 5998a314)
1 /*
2  *	Copyright (c) 1982 Regents of the University of California
3  */
4 #ifndef lint
5 static char sccsid[] = "@(#)asscan4.c 4.3 02/14/82";
6 #endif not lint
7 
8 #include "asscanl.h"
9 
10 #define	reg	register
11 #define	NUMSIZE	128	/* how many characters long a number can be */
12 #define	FLTCHAR(x)	(INCHARSET((x),(DIGIT|SIGN|FLOATEXP|POINT)))
13 
14 static char	numbuf[NUMSIZE];
15 
16 int number(ch, cpp)
17 	reg	int	ch;
18 		char	**cpp;
19 {
20 		int	radix;
21 		int	digit;		/* part of number being constructed */
22 	reg	int	intval;		/* number being constructed */
23 	reg	char	*cp;
24 	reg	char	*inbufptr;
25 		char	ch1;
26 		Bignum	floatnumber();
27 		Ovf	overflow;	/* overflow flag */
28 		int	maxstrlg;
29 
30 	inbufptr = *cpp;
31 	cp = numbuf;
32 	radix = 10;
33 
34 	switch(ch){
35 	case '0':
36 		switch(ch = getchar()){
37 		case 'b':
38 			yylval = -1;
39 			*cpp = inbufptr;
40 			return(BFINT);
41 		case 'f':
42 			/*
43 			 * Check if it is a local label by peeking ahead
44 			 */
45 			ch1 = getchar();
46 			ungetc(ch1);
47 			if (!FLTCHAR(ch1)){
48 				yylval = 1;
49 				*cpp = inbufptr;
50 				return(BFINT);
51 			}
52 			/*FALLTHROUGH*/
53 		case 'F': ch = 'f';	goto floatnum;
54 		case 'd':
55 		case 'D': ch = 'd';	goto floatnum;
56 		case 'h':
57 		case 'H': ch = 'h';	goto floatnum;
58 		case 'g':
59 		case 'G': ch = 'g';	goto floatnum;
60 
61 		case 'x':
62 		case 'X':
63 			ch = '0';
64 			radix = 16;
65 			break;
66 		case '0':
67 		case '1': case '2': case '3': case '4':
68 		case '5': case '6': case '7': case '8':
69 		case '9':
70 			radix = 8;
71 			break;
72 		default:	/* single 0 */
73 			ungetc(ch);
74 			intval = 0;
75 			goto smallnum;
76 		}
77 		break;
78 
79 	case '1': case '2': case '3': case '4':
80 	case '5': case '6': case '7': case '8':
81 	case '9':
82 		switch(ch1 = getchar()){
83 		case 'f':
84 			yylval = ((ch - '0') + 1);
85 			*cpp = inbufptr;
86 			return(BFINT);
87 		case 'b':
88 			yylval = -((ch - '0') + 1);
89 			*cpp = inbufptr;
90 			return(BFINT);
91 		default:
92 			ungetc(ch1);	/* put back non zero */
93 		}
94 		radix = 10;
95 		break;
96 	}
97 	intval = 0;
98 	/*
99 	 *	There is a character in ch that must be used to
100 	 *	cons up the number; we can't ungetc it
101 	 */
102 	do{
103 		digit = ch - '0';
104 		switch(radix){
105 		case 8:
106 			intval <<= 3;
107 			break;
108 		case 10:
109 			intval *= 10;
110 			break;
111 		case 16:
112 			intval <<= 4;
113 			if (INCHARSET(ch, HEXLDIGIT)){
114 				digit = (ch - 'a') + 10;
115 				break;
116 			}
117 			if (INCHARSET(ch, HEXUDIGIT)){
118 				digit = (ch - 'A') + 10;
119 				break;
120 			}
121 		}
122 		*cp++ = ch;
123 		/*
124 		 *	Build a negative number, then negate it
125 		 */
126 		intval -= digit;
127 
128 		ch = getchar();
129 		if(!INCHARSET(ch, DIGIT)){
130 			if (radix != 16)
131 				break;
132 			if(!INCHARSET(ch, (HEXLDIGIT|HEXUDIGIT)))
133 				break;
134 		}
135 	} while (1);
136 	ungetc(ch);
137 	*cp = 0;
138 	maxstrlg = cp - numbuf;
139 	/*
140 	 *	See if the number is too large for our previous calculation
141 	 */
142 	switch(radix){
143 	case 16:
144 		if (maxstrlg > 8)
145 			goto bignum;
146 		break;
147 	case 10:
148 		if (maxstrlg >= 10)
149 			goto bignum;
150 		break;
151 	case 8:
152 		if (maxstrlg > 11)
153 			goto bignum;
154 		if (maxstrlg == 11 && numbuf[0] > 3)
155 			goto bignum;
156 		break;
157 	}
158 	/*
159 	 *	Negate the number
160 	 */
161   smallnum: ;
162 	yylval = -intval;
163 	*cpp = inbufptr;
164 	return(INT);
165   bignum: ;
166 	yybignum = as_atoi(numbuf, radix, &overflow);
167 	*cpp = inbufptr;
168 	return(BIGNUM);
169   floatnum: ;
170 	*cpp = inbufptr;
171 	yybignum = floatnumber(ch, cpp);
172 	return(BIGNUM);
173 }
174 
175 #define	TOOLONG	if(cp == &numbuf[NUMSIZE]){if (passno == 2)yywarning(toolong); goto process;}
176 #define	scanit(sign) *cpp = inbufptr; error |= scanint(sign, &cp, cpp); inbufptr = *cpp; ch = getchar(); TOOLONG;
177 
178 Bignum floatnumber(fltradix, cpp)
179 	int	fltradix;
180 	char	**cpp;		/* call by copy return semantics */
181 {
182 		char	*cp;
183 		int	ch;
184 		char	*toolong = "Floating number too long.";
185 		char	*prologue =
186 			"Floating 0%c conflicts with exponent %c; choose %c";
187 		/*
188 		 *	This is not implemented yet:
189 		 *	overflow is set on floating overflow.
190 		 */
191 		Ovf	overflow;
192 		int	error;
193 		int	fractOK;
194 	reg	char	*inbufptr;
195 
196 	inbufptr = *cpp;
197 	cp = numbuf;
198 	error = 0;
199 	fractOK = 0;
200 
201 	scanit(1);
202 	if(INCHARSET(ch, POINT)){
203 		fractOK++;
204 		*cp++ = '.';
205 		scanit(0);
206 	}
207 	if(INCHARSET(ch, FLOATEXP)){
208 		fractOK++;
209 		if(ch != fltradix){
210 			if (passno == 2)
211 				yywarning(prologue, fltradix, ch, fltradix);
212 		}
213 		switch(fltradix){
214 		case 'd':
215 		case 'f':
216 			*cp++ = 'e';		/* will be read by atof() */
217 			break;
218 		default:
219 			*cp++ = fltradix;	/* will be read by bigatof() */
220 			break;
221 		}
222 		scanit(1);
223 	}
224 	if (error || fractOK == 0){
225 		yyerror("Badly formatted floating point number.");
226 	}
227 	ungetc(ch);
228 	*cp++ = 0;
229 
230   process: ;
231 	switch(fltradix){
232 	case 'f':	fltradix = TYPF;	break;
233 	case 'd':	fltradix = TYPD;	break;
234 	case 'g':	fltradix = TYPG;	nGHnumbers++; break;
235 	case 'h':	fltradix = TYPH;	nGHnumbers++; break;
236 	}
237 	/*
238 	 *	The overflow value is lost in the call to as_atof
239 	 */
240 	*cpp = inbufptr;
241 	return(as_atof(numbuf, fltradix, &overflow));
242 }
243 /*
244  *	Scan an optionally signed integer, putting back the lookahead
245  *	character when finished scanning.
246  */
247 int scanint(signOK, dstcpp, srccpp)
248 	int	signOK;
249 	char	**dstcpp;
250 	char	**srccpp;	/* call by copy return */
251 {
252 	int	ch;
253 	int	back = 0;
254 	reg	char	*inbufptr = *srccpp;
255 
256 	ch = getchar();
257 	while (INCHARSET(ch, SIGN)){
258 		if (signOK && !back)
259 			*((*dstcpp)++) = ch;
260 		else
261 			back = 1;
262 		ch = getchar();
263 	}
264 	while (INCHARSET(ch, DIGIT)){
265 		*((*dstcpp)++) = ch;
266 		ch = getchar();
267 	}
268 	ungetc(ch);
269 	*srccpp = inbufptr;
270 	return(back);
271 }
272