aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzlg <zlg@zlg.space>2015-02-20 21:35:39 -0800
committerzlg <zlg@zlg.space>2015-02-20 21:35:39 -0800
commitaf502c08e870ea3374d9c3d20d0e195aa3658f22 (patch)
treedd97fff3d41494ff3fcde45e3ec6ee2e0e1b4de1
parentSolve Exercise 5-18: error-recovering `dcl` (diff)
downloadknr-af502c08e870ea3374d9c3d20d0e195aa3658f22.tar.gz
knr-af502c08e870ea3374d9c3d20d0e195aa3658f22.tar.bz2
knr-af502c08e870ea3374d9c3d20d0e195aa3658f22.tar.xz
knr-af502c08e870ea3374d9c3d20d0e195aa3658f22.zip
Solve Exercise 5-19: Omit extra parens in `undcl`
-rw-r--r--ch5/5-19_undcl-no-redundant-parens.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/ch5/5-19_undcl-no-redundant-parens.c b/ch5/5-19_undcl-no-redundant-parens.c
new file mode 100644
index 0000000..4af4314
--- /dev/null
+++ b/ch5/5-19_undcl-no-redundant-parens.c
@@ -0,0 +1,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;
+}