aboutsummaryrefslogtreecommitdiff
path: root/ch5/5-19_undcl-no-redundant-parens.c
blob: 4af4314a46b9a25cb2cbb3602736d3406004a584 (plain)
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
#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* The C Programming Language: 2nd Edition
 *
 * Exercise 5-19: Modify `undcl` so that it does not add redundant parentheses
 * to declarations.
 *
 * Notes: The only circumstance that `undcl` will add extra parens is when it
 * comes across a pointer. So we look ahead and count pointers, then add them
 * all at once before output. It's a fairly simple fix.
 */

#define MAXTOKEN 100
#define BUFSIZE 100
#define MAXPTR 10

enum { NAME, PARENS, BRACKETS, TYPE };

int gettoken(void);
int getch(void);
void ungetch(int);

char buf[BUFSIZE];
int bufp = 0;
int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char out[1000];

int gettoken(void) {
	int c;
	char *p = token;
	while ((c = getch()) == ' ' || c == '\t') {
	}
	if (c == '(') {
		if ((c = getch()) == ')') {
			strcpy(token, "()");
			return tokentype = PARENS;
		} else {
			ungetch(c);
			return tokentype = '(';
		}
	} else if (c == '[') {
		for (*p++ = c; (*p++ = getch()) != ']'; ) {
		}
		*p = '\0';
		return tokentype = BRACKETS;
	} else if (isalpha(c)) {
		for (*p++ = c; isalnum(c = getch()); ) {
			*p++ = c;
		}
		*p = '\0';
		ungetch(c);
		return tokentype = NAME;
	} else {
		return tokentype = c;
	}
}

int getch(void) {
	return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) {
	if (bufp >= BUFSIZE) {
		printf("ungetch: Too many characters.\n");
	} else {
		buf[bufp++] = c;
	}
}

int main(void) {
	int type, pcount, i, c;
	char temp[MAXTOKEN];
	char p[MAXPTR];
	while (gettoken() != EOF) {
		strcpy(out, token);
		while ((type = gettoken()) != '\n') {
			if (type == PARENS || type == BRACKETS) {
				strcat(out, token);
			} else if (type == '*') {
				pcount++;
				while ((c = getch()) == '*' || c == ' ') {
					if (c == '*') {
						if (pcount < (MAXPTR - 1)) {
							pcount++;
						} else {
							break;
						}
					}
				}
				ungetch(c);
				for (i = 0; i < pcount; i++) {
					p[i] = '*';
				}
				pcount = 0;
				p[i] = '\0';
				sprintf(temp, "(%s%s)", p, out);
				strcpy(out, temp);
			} else if (type == NAME) {
				sprintf(temp, "%s %s", token, out);
				strcpy(out, temp);
			} else {
				printf("Invalid input at %s\n", token);
			}
		}
		printf("%s\n", out);
	}
	return 0;
}