/* * HTML syntax checker */ #include #include /* Start tags are stacked using "tag" structures: */ struct tag { struct tag *prev; /* pointer to previous start tag */ char name[11]; } *tail = NULL, *newtag; int caseno = 0; /* which test case are we processing? */ int lineno; /* line being processed */ int nlines; /* # of lines in this case */ void cleanup() /* clear the stack */ { struct tag *junk; while (tail != NULL) { junk = tail->prev; free(tail); tail = junk; } } /* Skip through n end of line characters */ void skiplines(int n) { int c; while (n) if ((c = getchar()) == '\n') n--; } int gettag() { char tagname[11]; /* name of the current tag */ int nchar; /* # of characters in the tag */ int endtag = 0; /* 0 = begin, 1 = end */ int c; /* # of input characters */ nchar = 0; c = getchar(); if (c == '/') endtag = 1; else ungetc(c,stdin); for(;;) { c = getchar(); if (!isupper(c)) break; /* end of tag? */ if (nchar == 10) { printf("line %d: too many/few characters in tag name.\n", lineno); skiplines(nlines-lineno+1); return 0; } else { tagname[nchar++] = c; } } if (c != '>') { printf("line %d: bad character in tag name.\n", lineno); if (c == '\n') lineno++; skiplines(nlines-lineno+1); return 0; } tagname[nchar] = '\0'; if (strlen(tagname) == 0) { printf("line %d: too many/few characters in tag name.\n", lineno); skiplines(nlines-lineno+1); return 0; } /* printf("Tag: "); if (endtag) putchar('/'); printf("%s\n", tagname); */ if (!endtag) { /* a new tag */ newtag = (struct tag *)malloc(sizeof(struct tag)); newtag->prev = tail; strcpy(newtag->name,tagname); tail = newtag; } else { /* end of a tagged region */ if (tail != NULL && !strcmp(tail->name,tagname)) { /* okay */ struct tag *temp; temp = tail; tail = tail->prev; free(temp); } else { if (tail != NULL) printf("line %d: expected \n", lineno, tail->name); else printf("line %d: no matching begin tag.\n", lineno); skiplines(nlines-lineno+1); return 0; } } return 1; } int process() { int c; lineno = 1; while (lineno <= nlines) { c = getchar(); if (c == '\n') lineno++; else if (c == '<') { if (!gettag()) return lineno; /* bad tag */ } } return 0; } main() { for(;;) { if (scanf("%d",&nlines) != 1) { printf("Unexpected end of file!\n"); exit(1); } if (nlines == 0) exit(0); /* end of input */ while (getchar() != '\n') ; /* skip through end of line */ /* NOT REALLY NEEDED? */ printf("Test Case %d\n", ++caseno); if (!process()) printf("OK\n"); cleanup(); putchar('\n'); } }