|
|
1.1 ! root 1: /* @(#)dag.c 1.4 */ ! 2: #include "stdio.h" ! 3: #include "ctype.h" ! 4: ! 5: #define NLINK 8 ! 6: ! 7: typedef struct node { ! 8: struct node *n_next; ! 9: struct node *n_left; ! 10: struct node *n_right; ! 11: char *n_name; ! 12: char *n_data; ! 13: int n_rcnt; ! 14: int n_visit; ! 15: int n_lcnt; ! 16: struct link *n_link; ! 17: } node; ! 18: ! 19: node *first = NULL; ! 20: node *last = NULL; ! 21: node *root = NULL; ! 22: ! 23: typedef struct link { ! 24: struct link *l_next; ! 25: struct node *l_node[NLINK]; ! 26: } link; ! 27: ! 28: #define isnamec(c) (isalpha(c)||isdigit(c)||c=='_') ! 29: #define NUL '\0' ! 30: #define BIGINT 32767 ! 31: ! 32: node *getnode(); ! 33: char *copy(); ! 34: int lines, nodes, links, chars; ! 35: int lineno = 0; ! 36: int lvmax = BIGINT; ! 37: char stdbuf[BUFSIZ]; ! 38: ! 39: main(argc, argv) ! 40: char *argv[]; ! 41: { ! 42: extern int optind; ! 43: extern char *optarg; ! 44: register node *np; ! 45: node *getnode(); ! 46: int c; ! 47: void reader(), dfs(); ! 48: ! 49: setbuf(stdout, stdbuf); ! 50: while ((c = getopt(argc, argv, "d:")) != EOF) ! 51: if (c == 'd') ! 52: { ! 53: if ((lvmax = getnum(optarg, 10)) == 0) ! 54: { ! 55: lvmax = BIGINT; ! 56: goto argerr; ! 57: } ! 58: } ! 59: else ! 60: argerr: ! 61: (void)fprintf(stderr, "dag: bad option %c ignored\n", c); ! 62: reader(stdin); ! 63: argc -= optind + 1; ! 64: if (argc <= 1) ! 65: for (np = first; np != NULL; np = np->n_next) ! 66: { ! 67: if (np->n_rcnt == 0) ! 68: dfs(np, 0); ! 69: } ! 70: else ! 71: while (--argc > 0) ! 72: dfs(getnode(*++argv), 0); ! 73: } ! 74: ! 75: getnum(p, base) ! 76: register int base; ! 77: register char *p; ! 78: { ! 79: register int n; ! 80: ! 81: n = 0; ! 82: while (isdigit(*p)) ! 83: n = n * base + (*p++ - '0'); ! 84: return(n); ! 85: } ! 86: ! 87: void reader(fp) ! 88: register FILE *fp; ! 89: { ! 90: register char *p1, *p2; ! 91: int c; ! 92: node *np, *getnode(); ! 93: char line[BUFSIZ], *copy(); ! 94: ! 95: while (getst(line, fp)) { ! 96: ++lines; ! 97: p1 = line; ! 98: while (isspace(*p1)) ! 99: ++p1; ! 100: if (*p1 == NUL) ! 101: continue; ! 102: p2 = p1; ! 103: while (isnamec(*p2)) ! 104: ++p2; ! 105: do { ! 106: c = *p2; ! 107: *p2++ = NUL; ! 108: } while (isspace(c)); ! 109: switch (c) { ! 110: ! 111: case '=': ! 112: np = getnode(p1); ! 113: while (isspace(*p2)) ! 114: ++p2; ! 115: if (np->n_data != NULL) { ! 116: (void)fprintf(stderr, "redefinition of %s\n", np->n_name); ! 117: (void)cfree(np->n_data); ! 118: } ! 119: np->n_data = copy(p2); ! 120: continue; ! 121: case ':': ! 122: np = getnode(p1); ! 123: while (*(p1 = p2) != NUL) { ! 124: while (isspace(*p1)) ! 125: ++p1; ! 126: p2 = p1; ! 127: while (isnamec(*p2)) ! 128: ++p2; ! 129: (void)addlink(np, getnode(p1)); ! 130: if (*p2 != NUL) ! 131: *p2++ = NUL; ! 132: } ! 133: continue; ! 134: } ! 135: } ! 136: } ! 137: ! 138: getst(s, fp) ! 139: char *s; ! 140: FILE *fp; ! 141: { ! 142: register i, c; ! 143: ! 144: i = 0; ! 145: while ((c = getc(fp)) != EOF) { ! 146: if (c == '\n') { ! 147: *s = NUL; ! 148: return 1; ! 149: } ! 150: if (i++ < BUFSIZ) ! 151: *s++ = c; ! 152: } ! 153: return 0; ! 154: } ! 155: ! 156: char * ! 157: copy(s) ! 158: char *s; ! 159: { ! 160: char *p, *strcpy(), *calloc(); ! 161: void exit(); ! 162: ! 163: p = calloc(sizeof(char), (unsigned)(strlen(s)+2)); ! 164: if (p == NULL) { ! 165: (void)fprintf(stderr, "too many characters\n"); ! 166: exit(1); ! 167: } ! 168: (void)strcpy(p, s); ! 169: chars += strlen(p); ! 170: return p; ! 171: } ! 172: ! 173: node * ! 174: getnode(name) ! 175: char *name; ! 176: { ! 177: register i; ! 178: register node *np, **pp; ! 179: void exit(); ! 180: char *copy(), *calloc(); ! 181: ! 182: pp = &root; ! 183: while ((np = *pp) != NULL) { ! 184: i = strcmp(name, np->n_name); ! 185: if (i > 0) ! 186: pp = &np->n_right; ! 187: else if (i < 0) ! 188: pp = &np->n_left; ! 189: else ! 190: return np; ! 191: } ! 192: *pp = (node *)calloc(sizeof(node), 1); ! 193: if ((np = *pp) == NULL) { ! 194: (void)fprintf(stderr, "too many nodes"); ! 195: exit(1); ! 196: } ! 197: ++nodes; ! 198: np->n_name = copy(name); ! 199: np->n_data = NULL; ! 200: if (first == NULL) ! 201: first = np; ! 202: if (last != NULL) ! 203: last->n_next = np; ! 204: last = np; ! 205: np->n_next = NULL; ! 206: np->n_left = np->n_right = NULL; ! 207: np->n_rcnt = np->n_lcnt = np->n_visit = 0; ! 208: np->n_link = NULL; ! 209: return np; ! 210: } ! 211: ! 212: addlink(np, rp) ! 213: node *np, *rp; ! 214: { ! 215: register i, j; ! 216: char *calloc(); ! 217: link *lp, **pp; ! 218: void exit(); ! 219: ! 220: i = j = 0; ! 221: pp = &np->n_link; ! 222: while ((lp = *pp) != NULL && i < np->n_lcnt) { ! 223: if (rp == lp->l_node[j]) ! 224: return 0; ! 225: if (++j >= NLINK) { ! 226: j = 0; ! 227: pp = &lp->l_next; ! 228: } ! 229: ++i; ! 230: } ! 231: if (lp == NULL) { ! 232: *pp = (link *)calloc(sizeof(link), 1); ! 233: if ((lp = *pp) == NULL) { ! 234: (void)fprintf(stderr, "too many links\n"); ! 235: exit(1); ! 236: } ! 237: ++links; ! 238: lp->l_next = NULL; ! 239: } ! 240: lp->l_node[j] = rp; ! 241: if (np != rp) ! 242: ++rp->n_rcnt; ! 243: ++np->n_lcnt; ! 244: return 1; ! 245: } ! 246: ! 247: void dfs(np, lv) ! 248: register ! 249: node *np; ! 250: { ! 251: register i, j; ! 252: link *lp; ! 253: ! 254: if (np == NULL || lv > lvmax) ! 255: return; ! 256: i = 0; ! 257: (void)printf("%d\t",++lineno); ! 258: while (i++ < lv) ! 259: (void)putchar('\t'); ! 260: (void)printf("%s: ", np->n_name); ! 261: if (np->n_visit > 0) { ! 262: (void)printf("%d\n", np->n_visit); ! 263: return; ! 264: } ! 265: if (np->n_data != NULL) ! 266: (void)printf("%s\n", np->n_data); ! 267: else ! 268: (void)printf("<>\n"); ! 269: np->n_visit = lineno; ! 270: i = j = 0; ! 271: lp = np->n_link; ! 272: while (i < np->n_lcnt && lp != NULL) { ! 273: dfs(lp->l_node[j], lv+1); ! 274: if (++j >= NLINK) { ! 275: j = 0; ! 276: lp = lp->l_next; ! 277: } ! 278: ++i; ! 279: } ! 280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.