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