Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
263 dpurdie 1
/*
2
	CPP V5 -- utilities.
3
 
4
	Source:  utl.c
5
	Started: October 7, 1985
6
	Version:
7
		July 21, 1988
8
		March 3, 1989
9
			bug fix to skip_ws() and copy_ws().
10
		August 1, 1989
11
			Support for C++ style single-line comments added to
12
			skip_pp(), skip_ws() and copy_ws().
13
 
14
	Written by Edward K. Ream.
15
	This software is in the public domain.
16
 
17
	See the read.me file for disclaimer and other information.
18
*/
19
 
20
#include "cpp.h"
21
 
22
/*
23
	Return the value of a character constant.
24
*/
25
int
26
char_val(s)
27
register char *s;
28
{
29
	int val;
30
 
31
	if (*s != '\\') {
32
		return (int) *s;
33
	}
34
	s++;
35
	switch (*s) {
36
	case 'b':	return '\b';
37
	case 'f':	return '\f';
38
	case 'n':	return '\n';
39
	case 'r':	return '\r';
40
	case 't':	return '\t';
41
	case '\'':	return '\'';
42
	case '\\':	return '\\';
43
 
44
	default:
45
		if (*s < '0' || *s > '7') {
46
			return (int)*s;
47
		}
48
		val = 0;
49
		while (*s >= '0' && *s <= '7') {
50
			val = val * 8 + (int)*s - '0';
51
			s++;
52
		}
53
		return val;
54
	}
55
}
56
 
57
/*
58
	Re-evaluate a string constant; this may shorten it
59
 
60
	Return its length; it may contain imbedded zeroes once processed
61
 
62
	CAUTION: if the string is transformed, it is always shortened.  Callers
63
	of this routine may count on that fact.
64
*/
65
unsigned int
66
str_val(d)
67
register unsigned char *d;
68
{
69
	register unsigned char val, *dd, *s;
70
	TICK("str_val");
71
 
72
	/* outer loop to scan the string */
73
	s = dd = d;
74
	while (*s) {
75
		if (*s != '\\') {
76
			*d++ = *s++;
77
			continue;
78
		}
79
		++s;
80
		switch (*s) {
81
		case 'b':	*d++ = '\b'; ++s; break;
82
		case 'f':	*d++ = '\f'; ++s; break;
83
		case 'n':	*d++ = '\n'; ++s; break;
84
		case 'r':	*d++ = '\r'; ++s; break;
85
		case 't':	*d++ = '\t'; ++s; break;
86
		case '\'':	*d++ = '\''; ++s; break;
87
		case '\\':	*d++ = '\\'; ++s; break;
88
 
89
		default:
90
			if (*s < '0' || *s > '7') {
91
				continue;
92
			}
93
			val = 0;
94
			while (*s >= '0' && *s <= '7') {
95
				val = val * 8 + *s - '0';
96
				s++;
97
			}
98
			*d++ = val;
99
		}
100
	}
101
	*d++ = '\0';
102
	TRACEP("str_val", printf("returns length %d\n", (int)(d - dd)));
103
	return (unsigned int)(d - dd);
104
}
105
 
106
/*
107
	Return the value of a string of digits in a given radix.
108
*/
109
int
110
conv2i(string, radix)
111
char *string;
112
int radix;
113
{
114
	register int value;
115
	register int digit;
116
 
117
	TICK("conv2i");
118
 
119
	value = 0;
120
	while (digit = *string++) {
121
		if (digit >= 'a' && digit <= 'z') {
122
			digit = digit - 'a' + 10;
123
		}
124
		else if (digit >= 'A' && digit <= 'Z') {
125
			digit = digit - 'A' + 10;
126
		}
127
		else {
128
			digit = digit - '0';
129
		}
130
		value = (value * radix) + digit;
131
	}
132
	return value;
133
}
134
 
135
/*
136
	Convert a signed integer n to a string s[].
137
	The length of s must be large enough to hold the result.
138
*/
139
void
140
conv2s (a, s)
141
int a;
142
register char *s;
143
{
144
	register char *d, *ss;
145
	register int sn;
146
	register unsigned long n;
147
	char temp [INT_DIGITS];
148
 
149
	TICK("conv2s");
150
 
151
	/* Do the sign and handle 0x8000 correctly */
152
	if (a >= 0) {
153
		sn = 0;
154
		/* these casts ARE NOT redundant: DO NOT fix them! */
155
		/* see note in lint.doc about unsigned extending casts */
156
		n = (unsigned long) (long) a;
157
	}
158
	else {
159
		sn = 1;
160
		n = (unsigned long) (long) (-a);
161
	}
162
 
163
	/* put digits in reverse order into temp */
164
	d = &temp[0];
165
	*d++ = 0;
166
	if (n) while (n) {
167
		/* NOTE: in assembly, we would divide once */
168
		*d++ = (char)(n % 10) + '0';
169
		n = n / 10;
170
	}
171
	else {
172
		*d++ = '0';
173
	}
174
 
175
	/* insert the sign */
176
	if (sn) {
177
		*d++ = '-';
178
	}
179
 
180
	/* Reverse temp into s. */
181
	ss = s;
182
	while(*ss++ = *--d) {};
183
 
184
	TRACE("conv2s", printf("conv2s returns: %s\n", s));
185
}
186
 
187
/*
188
	Convert a long n to a string s[].
189
	The length of s must be large enough to hold the result.
190
*/
191
void
192
convl2s (a, s)
193
long a;
194
register char *s;
195
{
196
	register char *d, *ss;
197
	register int sn;
198
	register unsigned long n;
199
	char temp [LONG_DIGITS];
200
 
201
	TICK("convl2s");
202
 
203
	/* Do the sign and handle 0x80000000 correctly */
204
	if (a >= 0) {
205
		sn = 0;
206
		n = (unsigned long) a;
207
	}
208
	else {
209
		sn = 1;
210
		n = (unsigned long) (-a);
211
	}
212
 
213
	/* put digits in reverse order into temp */
214
	d = &temp[0];
215
	*d++ = 0;
216
	if (n) while (n) {
217
		/* NOTE: in assembly, we would divide once */
218
		*d++ = (char)(n % 10) + '0';
219
		n = n / 10;
220
	}
221
	else {
222
		*d++ = '0';
223
	}
224
 
225
	/* insert the sign */
226
	if (sn) {
227
		*d++ = '-';
228
	}
229
 
230
	/* Reverse temp into s. */
231
	ss = s;
232
	while(*ss++ = *--d) {};
233
 
234
	TRACE("convl2s", printf("convl2s (%ld): %s\n", a, s));
235
}
236
 
237
/*
238
	Convert a long n to a string s[], minimum digit count c.
239
	The length of s must be large enough to hold any result.
240
*/
241
void
242
conul2sc(n, s, c)
243
register unsigned long n;
244
register char *s;
245
register int c;
246
{
247
	register char *d, *ss;
248
	char temp [LONG_DIGITS];
249
 
250
	TICK("conul2sc");
251
 
252
	/* put digits in reverse order into temp */
253
	d = &temp[0];
254
	*d++ = 0;
255
	while (n) {
256
		/* NOTE: in assembly, we would divide once */
257
		*d++ = (char)(n % 10) + '0';
258
		n /= 10;
259
		if (c > 0) {
260
			c--;
261
		}
262
	}
263
	while (c > 0) {
264
		c--;
265
		*d++ = '0';
266
	}
267
 
268
	/* Reverse temp into s. */
269
	ss = s;
270
	while(*ss++ = *--d) {};
271
 
272
	TRACE("conul2sc", printf("conul2sc returns: %s\n", s));
273
}
274
 
275
/*
276
	Convert a long n to a hex string s[], minimum digit count c.
277
	The length of s must be large enough to hold any result.
278
*/
279
void
280
conl2h(n, s, c)
281
register unsigned long n;
282
register char *s;
283
register int c;
284
{
285
	register char *d, *ss;
286
	char temp [LONG_DIGITS];
287
 
288
	TICK("conl2h");
289
 
290
	/* put digits in reverse order into temp */
291
	d = &temp[0];
292
	*d++ = 0;
293
	while (n) {
294
		*d = ((char)n & 15) + '0';
295
		if (*d > '9') {
296
			*d += 7;
297
		}
298
		d++;
299
		n >>= 4;
300
		if (c > 0) {
301
			c--;
302
		}
303
	}
304
	while (c > 0) {
305
		c--;
306
		*d++ = '0';
307
	}
308
 
309
	/* Reverse temp into s. */
310
	ss = s;
311
	while(*ss++ = *--d) {};
312
 
313
	TRACE("conl2h", printf("conl2h returns: %s\n", s));
314
}
315
 
316
/*
317
	Skip blanks and tabs,  but not newlines.
318
*/
319
void
320
skip_bl()
321
{
322
	TICKB("skip_bl");
323
 
324
	while (ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f') {
325
		sysnext();
326
	}
327
 
328
	RETURN_VOID("skip_bl");
329
}
330
 
331
/*
332
	Skip characters up to but NOT including a newline.
333
*/
334
void
335
skip_1line()
336
{
337
	TICKB("skip_1line");
338
 
339
	while (ch != END_FILE && ch != '\n') {
340
		sysnext();
341
	}
342
 
343
	RETURN_VOID("skip_1line");
344
}
345
 
346
/*
347
	Skip characters up to and including a newline.
348
*/
349
void
350
skip_past()
351
{
352
	TICKB("skip_past");
353
 
354
	while (ch != END_FILE && ch != '\n') {
355
		sysnext();
356
	}
357
 
358
	if (ch == '\n') {
359
		sysnext();
360
		if (com_flag) {
361
			sysnlput();
362
		}
363
		bump_line();
364
	}
365
 
366
	RETURN_VOID("skip_past");
367
}
368
 
369
/*
370
	Skip to the end of the current preprocessor directive.
371
	I.e., skip to the first newline not contained in a comment.
372
*/
373
void
374
skip_pp()
375
{
376
	TICKB("skip_pp");
377
 
378
	while (ch != '\n' && ch != END_FILE) {
379
		if (ch == '/') {
380
			/* Possible comment. */
381
			sysnext();
382
			if (ch == '*') {
383
				sysnext();
384
				skip_comment();
385
			}
386
			else if (slc_flag && ch == '/') {
387
				/* 8/1/89 Single-line comment */
388
				while (ch != END_FILE && ch != '\n') {
389
					sysnext();
390
				}
391
				RETURN_VOID("skip_pp");
392
			}
393
			else {
394
				syspushback(ch);
395
				ch = '/';
396
				RETURN_VOID("skip_pp");
397
			}
398
		}
399
		else {
400
			sysnext();
401
		}
402
	}
403
	RETURN_VOID("skip_pp");
404
}
405
 
406
/*
407
	Skip blanks, tabs, and comments.
408
	Also skip newlines if nl_flag is TRUE;
409
*/
410
void
411
skip_ws(nl_flag)
412
bool nl_flag;
413
{
414
	TRACEPB("skip_ws", printf("(%s)\n", pr_bool(nl_flag)));
415
 
416
	for(;;) {
417
 
418
		switch(ch) {
419
 
420
		case ' ':
421
		case '\t':
422
		case '\f':
423
		case '\v':
424
			sysnext();
425
			continue;
426
 
427
		case '\n':
428
			if (nl_flag) {
429
				bump_line();
430
				sysnext();
431
				continue;
432
			}
433
			else {
434
				/* 3/3/89 */
435
				goto done;
436
			}
437
 
438
		case '/':
439
			sysnext();
440
			if (ch == '*') {
441
				sysnext();
442
				skip_comment();
443
				continue;
444
			}
445
			else if (slc_flag && ch == '/') {
446
				/* 8/1/89 Single-line comment */
447
				while (ch != END_FILE && ch != '\n') {
448
					sysnext();
449
				}
450
				continue;
451
			}
452
			else {
453
				syspushback(ch);
454
				ch = '/';
455
				goto done;
456
			}
457
 
458
		default:
459
			goto done;
460
		}
461
	}
462
done:
463
	RETURN_VOID("skip_ws");
464
}
465
 
466
/*
467
	Copy blanks, tabs and comments to the output.
468
	Also copy newlines if nl_flag is TRUE;
469
*/
470
void
471
copy_ws(nl_flag)
472
bool nl_flag;
473
{
474
	TRACEPB("copy_ws", printf("(%s)\n", pr_bool(nl_flag)));
475
 
476
	for(;;) {
477
 
478
		switch(ch) {
479
 
480
		case ' ':
481
		case '\t':
482
		case '\f':
483
		case '\v':
484
			syscput(ch);
485
			sysnext();
486
			continue;
487
 
488
		case '\n':
489
			if (nl_flag) {
490
				bump_line();
491
				sysnlput();
492
				sysnext();
493
				continue;
494
			}
495
			else {
496
				/* 3/3/89 */
497
				goto done;
498
			}
499
 
500
		case '/':
501
			sysnext();
502
			if (ch == '*') {
503
				sysnext();
504
				syscput('/');
505
				syscput('*');
506
				copy_comment();
507
				continue;
508
			}
509
			else if (slc_flag && ch == '/') {
510
				/* 8/1/89 Single-line comment */
511
				sysnext();
512
				syscput('/');
513
				syscput('/');
514
				while (ch != END_FILE && ch != '\n') {
515
					syscput(ch);
516
					sysnext();
517
				}
518
				continue;
519
			}
520
			else {
521
				syspushback(ch);
522
				ch = '/';
523
				goto done;
524
			}
525
 
526
		default:
527
			goto done;
528
		}
529
	}
530
done:
531
	RETURN_VOID("copy_ws");
532
}
533
 
534
/*
535
	Process a non-fatal error messages.
536
*/
537
void
538
error(message)
539
char *message;
540
{
541
	TICK("error");
542
	syscsts();
543
	t_errcount++;
544
	if (t_inlevel == 0) {
545
		printf("line %3d: %s\n", t_line, message);
546
	}
547
	else {
548
		printf("line %3d, %s: %s\n", t_line, t_file, message);
549
	}
550
}
551
 
552
void
553
err2(mess1, mess2)
554
char *mess1;
555
char *mess2;
556
{
557
	TICK("err2");
558
	syscsts();
559
	t_errcount++;
560
	if (t_inlevel == 0) {
561
		printf("line %3d: %s%s\n", t_line, mess1, mess2);
562
	}
563
	else {
564
		printf("line %3d, %s: %s%s\n", t_line, t_file, mess1, mess2);
565
	}
566
}
567
 
568
void
569
err3(mess1, mess2, mess3)
570
char *mess1;
571
char *mess2;
572
char *mess3;
573
{
574
	TICK("err3");
575
	syscsts();
576
	t_errcount++;
577
	if (t_inlevel == 0) {
578
		printf("line %3d: %s%s%s\n", t_line, mess1, mess2, mess3);
579
	}
580
	else {
581
		printf("line %3d, %s: %s%s%s\n",
582
			t_line, t_file, mess1, mess2, mess3);
583
	}
584
}
585
 
586
/*
587
	Give an error message and exit.
588
*/
589
void
590
fatal(message)
591
char * message;
592
{
593
	printf("\nOh dear.  I can't go on like this...\n\n");
594
	printf("line %3d, %s: %s\n", t_line, t_file, message);
595
 
596
	TRACE("dump", m_stat());
597
	TRACE("dump", sl_dump());
598
	sysabort();
599
 
600
}
601
 
602
/*
603
	Internal error.
604
*/
605
void
606
syserr(message)
607
char *message;
608
{
609
	printf("\nOh dear.  There is something wrong with me...\n\n");
610
	printf("line %3d, %s: %s\n", t_line, t_file, message);
611
 
612
	TRACE("dump", m_stat());
613
	TRACE("dump", sl_dump());
614
	sysabort();
615
}
616
 
617
/*
618
	Process a non-fatal warning message.
619
*/
620
void
621
warning(message)
622
char *message;
623
{
624
	TICK("warning");
625
	syscsts();
626
	if (t_inlevel == 0) {
627
		printf("line %3d: (Warning) %s\n", t_line, message);
628
	}
629
	else {
630
		printf("line %3d, %s: (Warning) %s\n",
631
			t_line, t_file, message);
632
	}
633
}
634
 
635
void
636
warn2(mess1, mess2)
637
char *mess1;
638
char *mess2;
639
{
640
	TICK("warn2");
641
	syscsts();
642
	if (t_inlevel == 0) {
643
		printf("line %3d: (Warning) %s%s\n", t_line, mess1, mess2);
644
	}
645
	else {
646
		printf("line %3d, %s: (Warning) %s%s\n",
647
			t_line, t_file, mess1, mess2);
648
	}
649
}
650
 
651
void
652
warn3(mess1, mess2, mess3)
653
char *mess1;
654
char *mess2;
655
char *mess3;
656
{
657
	TICK("warn3");
658
	syscsts();
659
	if (t_inlevel == 0) {
660
		printf("line %3d: (Warning) %s%s%s\n",
661
			t_line, mess1, mess2, mess3);
662
	}
663
	else {
664
		printf("line %3d, %s: (Warning) %s%s%s\n",
665
			t_line, t_file, mess1, mess2, mess3);
666
	}
667
}