📄 mref.c
字号:
int n;{/* Scan b for the string s and truncate it there if found. */ char *p; p = string; while (*p != '\0') { if (strncmp(p, s, n) == 0) { *p = 0; if (*(p - 1) == ' ') *(p - 1) = 0; return; } else { p++; } }}char *backup(q)char *q;{/* Back the pointer q up to the start of the word it points to. */ while (*q != ' ' && *q != '*') q--; return(q + 1);}void enter_sym(p, value, type)char *p; /* pointer to name of symbol */int value; /* line number on which symbol occurs */int type; /* PUB, PRIV, EXT, DEF, SYM */{/* Enter a symbol in the hash table. A symbol may be define in FS and again * in MM, etc. Up to 3 definitions are stored. */ int h, len; struct symtab *hp; if (nsymbols >= NSYMS) panic("symbol table overflow"); /* Watch out for the #define PUBLIC line, etc. */ if (strlen(p) == 0) return; if (strcmp(p, "PUBLIC") == 0) return; if (strcmp(p, "PRIVATE") == 0) return; if (strcmp(p, "EXTERN") == 0) return; if (strcmp(p, "int") == 0) return; if (strcmp(p, "char") == 0) return; if (strcmp(p, "void") == 0) return; strip(p, "(", 1); h = find_slot(p); hp = &symtab[h]; len = strlen(p); if (len > SYM_SIZE) len = SYM_SIZE; /* Enter the symbol. Multiple definitions are allowed. */ strncpy(hp->sym_name, p, (size_t)len);/* entry is SYM_SIZE+1 for \'0' */ hp->sym_type = type; hp->sym_val = value; nsymbols++;}int find_slot(p)char *p;{/* Hash the string and return an index into the hash table. If a collision * occurs, the first consecutive free slot is used. */ unsigned int h; /* Search all entries starting at h for a free slot. */ h = hash(p); while (1) { if (symtab[h].sym_type == 0) return((int) h); /* empty slot */ h = (h + 1) % NSYMS; /* try next entry */ }}int lookup(p)char *p;{/* Is p is in the symbol table? Return slot if it is present, -1 if absent. */ unsigned int h; h = hash(p); while (1) { if (symtab[h].sym_type == 0) return(-1); /* not present */ if (strcmp(p, symtab[h].sym_name) == 0) return ((int) h); h = (h + 1) % NSYMS; }}unsigned int hash(p)char *p;{/* Compute and return the hash code of p. */ int i, n; unsigned h; n = strlen(p); if (n > SYM_SIZE) n = SYM_SIZE; h = 0; for (i = 0; i < n; i++) { h += 23 * i * (int) *p; p++; } h = h % NSYMS; return(h);}void print_sym(){/* Print all the definitions. */ int n, k, i, limit; struct symtab *ap, *bp, *cp; n = compact(); /* compact the symbol table */ if (n < 0 || n > NSYMS) panic("compact returned invalid value"); sort(n); /* sort the symbol table */ /* Print the symbol table. */ if (tflag) { /* Produce the symbol.out file for troff. */ i = 0; limit = stride; while (1) { while (i < limit) { ap = &symtab[i]; bp = &symtab[i + stride]; cp = &symtab[i + 2 * stride]; if (ap < &symtab[n]) fprintf(sym, "%s\t%d", ap->sym_name, ap->sym_val); if (bp < &symtab[n]) fprintf(sym, "\t%s\t%d", bp->sym_name, bp->sym_val); if (cp < &symtab[n]) fprintf(sym, "\t%s\t%d", cp->sym_name, cp->sym_val); fprintf(sym, "\n"); i++; } fprintf(sym, ".bp\n"); if (cp >= &symtab[n - 1]) return; i += 2 * stride; stride = stride2; /* 1st page may be different */ limit = i + stride; } } else { /* Produce the flat version of symbol.out. */ for (ap = &symtab[0]; ap < &symtab[n]; ap++) { k = strlen(ap->sym_name); fprintf(sym, "%s%s %5d %s\n", ap->sym_name, &spaces[k], ap->sym_val, ppmap[ap->sym_type]); } }}int compact(){/* Compact the symbol table to make sorting more efficient. */ unsigned int d; struct symtab *ap, *bp; bp = &symtab[NSYMS - 1]; /* bp points to last entry */ for (ap = &symtab[0]; ap < bp; ap++) { if (ap->sym_type != 0) continue; /* skip used slots. */ /* Ap points to an empty slot. Find a full one and swap them. */ while (bp->sym_type == 0 && bp > symtab) bp--; /* skip empty slots */ if (bp <= ap) { d = ap - symtab; return(d); } swap(ap, bp); } return(ap - symtab);}void swap(ap, bp)struct symtab *ap, *bp;{/* Swap two symbol table entries. */ struct symtab xp; xp = *ap; *ap = *bp; *bp = xp;}void sort(n)int n; /* number of nonnull entries in symtab */{/* Sort the symbol table. Use bubble sort. */ int s; struct symtab *ap, *bp; for (ap = &symtab[0]; ap < &symtab[n - 1]; ap++) { for (bp = ap + 1; bp < &symtab[n]; bp++) { s = strcmp(ap->sym_name, bp->sym_name); if (s < 0) continue; if (s == 0 && ap->sym_type < bp->sym_type) continue; swap(ap, bp); } }}void gen_xref(file)char *file;{/* Build the cross reference listing. Reread file, looking up all * symbols in the hash table. On every hit, an entry written to the temporary * file. Later they will be sorted and printed. */ int i, k; register char *p; char c; FILE *f; if ((f = fopen(file, "r")) == NULL) { fprintf(stderr, "%s: cannot open %s\n", prog_name, file); exit(1); } while (1) { /* Each iteration of this outer loop reads one line of the file. */ if (fgets(line_buf, LINE_SIZE, f) == NULL) { /* End of file hit. */ fclose(f); if (cur_line % page_len != 0) { k = cur_line % page_len; if (k > 0) k = page_len - k; cur_line += k; } return; } ntokens = 0; p = line_buf; if (comment) { p = skip_comment(p); if (*p == '\n') { cur_line++; continue; /* we haven't seen end yet */ } } c = *p; while (c != '\n') { /* This loop scans the line looking for tokens. */ if (isalpha(c) || c == '_') { /* This is the start of a token. */ token[ntokens++] = p; /* store start of token */ while (isalnum(*p) || *p == '_') p++; c = *p; /* save character after token */ *p = 0; /* terminate the token */ continue; } /* Check to see if it is a comment. */ if (c == '/' && *(p + 1) == '*') { p = skip_comment(p + 2); /* it's a comment */ c = *p; continue; } /* Check to see if it is a string. */ if (c == '"') { p++; while (*p != '"') p++; p++; c = *p; continue; } /* Check to see if it is a character constant. */ if (c == '\'') { p++; while (*p != '\'') { if (*p == '\\') p++; p++; } p++; c = *p; continue; } /* It is not a token or a comment, just ignore it. */ p++; c = *p; } /* Process the token array just constructed. This is where * the cross references are written to TMP_FILE. Put out * leading zeros so that sort will get them right. */ for (i = 0; i < ntokens; i++) { p = token[i]; if (strlen(p) > SYM_SIZE) *(p + SYM_SIZE) = 0; k = lookup(p); if (k >= 0) { fprintf(tmp, "%s ", p); if (cur_line < 10) fprintf(tmp, "0000%d\n", cur_line); else if (cur_line < 100) fprintf(tmp, "000%d\n", cur_line); else if (cur_line < 1000) fprintf(tmp, "00%d\n", cur_line); else if (cur_line < 10000) fprintf(tmp, "0%d\n", cur_line); else fprintf(tmp, "%d\n", cur_line); } } cur_line++; }}char *skip_comment(p)char *p;{/* Skip a comment. */ while (1) { if (*p == '*' && *(p + 1) == '/') { comment = 0; return(p + 2); } if (*p == '\n') { comment = 1; /* next line is still comment. */ return(p); } p++; }}void collect_xref(){/* Sort the cross references and format them. */ int i, values[MAX_VALUES], used, nval, s, flag; register char *p; char *pname, *pnum; char cur[SYM_SIZE + 1]; /* name currently being processed. */ /* Use the sort program to sort the file where the cross references * have been accumulating. */ fclose(tmp); /* close temporary file to flush the buffer */ sort_xref(); /* sort the cross references */ unlink(TMP_FILE); /* temporary file is not needed any more */ /* Open the sorted file to read it back. */ sortf = fopen(SORTED_FILE, "r"); if (sortf == NULL) { fprintf(stderr, "%s: cannot read back %s \n", prog_name, SORTED_FILE); exit(2); } /* Read back each line in turn. */ used = 0; while (1) { if (fgets(line_buf, LINE_SIZE, sortf) == NULL) { /* EOF seen. Flush current line and return. */ fprintf(xr, "\n"); fclose(xr); unlink(SORTED_FILE); return; } /* Terminate both of the tokens contained on each line with 0s. */ p = line_buf; pname = p; while (*p != ' ') p++; *p = 0; p++; pnum = p; while (*p != '\n') p++; *p = 0; /* Is this name the one we are currently working on? */ if (used == 0 || strcmp(pname, cur) != 0) { nval = new_name(cur, used, pname, values); xcount = nval; /* # refs on this line so far */ prev_ref = -1; } used = 1; /* For every reference, see if it is a definition. If so, do * not print it, since the definitions are printed when the * symbol is encountered for the first time. */ s = atoi(pnum); flag = 0; for (i = 0; i < nval; i++) if (s == values[i]) flag = 1; if (flag) continue; if (mflag && s == prev_ref) continue; /* max 1 citation/line */ if (xcount > 0 && xcount % MAX_PER_LINE == 0) { if (tflag) fprintf(xr, "\t"); else fprintf(xr, " "); } /* The next line prints a reference on the cross reference listing. */ if (tflag) fprintf(xr, "\t%d", s); else fprintf(xr, " %5d", s); prev_ref = s; /* remember it for subsequent use */ xcount++; /* number of symbols printed on this line */ if (xcount % MAX_PER_LINE == 0) fprintf(xr, "\n"); }}int new_name(cur, used, pname, values)char *cur; /* storage for current name */int used; /* 0 only on first call. */char *pname; /* pointer to the new name */int values[]; /* all the definitions of the new name */{/* A new name has been read. Finish off the old one and prepare new one. */ int slot, nval, i, j, type, temp; /* If a name is currently in use (all except first time), finish it. */ if (used && xcount % MAX_PER_LINE > 0) fprintf(xr, "\n"); xcount = 0; /* Copy the new name in place and fetch its definitions. Multiple * definitions are allowed, e.g., do_fork may appear in FS and also * in MM, but if they are different types (e.g., one PUBLIC and one * PRIVATE) only one of them will be included in the listing, to * avoid messing up the layout. */ strcpy(cur, pname); cur[SYM_SIZE] = 0; slot = lookup(pname); nval = 0; while (symtab[slot].sym_type > 0) { if (strcmp(pname, symtab[slot].sym_name) == 0) { values[nval++] = symtab[slot].sym_val; type = symtab[slot].sym_type; if (nval == MAX_VALUES) break; } slot = (slot + 1) % NSYMS; } /* Sort the values. */ for (i = 0; i < nval - 1; i++) { for (j = i + 1; j < nval; j++) { if (values[i] > values[j]) { temp = values[i]; values[i] = values[j]; values[j] = temp; } } } /* Print the line in the cross reference map that contains the symbol. */ fprintf(xr, "%s", pname); if (tflag) { fprintf(xr, "\t%s\\fB", ppmap2[type]); for (i = 0; i < nval; i++) fprintf(xr, "\t%d", values[i]); fprintf(xr, "\\fR"); } else { i = strlen(pname); fprintf(xr, "%s %s ", &spaces[i], ppmap2[type]); for (i = 0; i < nval; i++) fprintf(xr, "%5d ", values[i]); } return(nval);}void sort_xref(){/* Sort the cross reference file by forking off a copy of 'sort'. */ int status, pid; pid = fork(); if (pid > 0) { /* Parent just waits. */ wait(&status); if (status != 0) panic("couldn't sort cross references"); } else { /* Child execs sort. */ close(0); close(1); if (open(TMP_FILE, O_RDONLY) < 0) exit(1); if (creat(SORTED_FILE, 0644) < 0) exit(2); execl("/bin/sort", "sort", (char *) 0); execl("/usr/bin/sort", "sort", (char *) 0); exit(3); }}void output_macros(f, text)FILE *f;char *text[];{/* Output troff commands. */ int i; i = 0; while (text[i] != (char *) 0) { fprintf(f, text[i]); i++; }}void sym_macros(){}void xref_macros(){}void panic(s)char *s;{ fprintf(stderr, "%s: %s\n", prog_name, s); exit(2);}void usage(){ fprintf(stderr, "Usage: %s [-<n>] [-dlmtsx] [-p pagenr] file ... \n", prog_name);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -