1: /* 2: ** fmtxref.c 3: ** 4: ** format the output of the C cross referencer. 5: ** this program relies on the fact that its input 6: ** is sorted and uniq-ed. 7: ** 8: ** Arnold Robbins, Information and Computer Science, Georgia Tech 9: ** gatech!arnold 10: ** Copyright (c) 1984 by Arnold Robbins. 11: ** All rights reserved. 12: ** This program may not be sold, but may be distributed 13: ** provided this header is included. 14: */ 15: 16: #include <stdio.h> 17: #include <ctype.h> 18: 19: #define TRUE 1 20: #define FALSE 0 21: 22: #define MAXID 121 /* maximum lengths of identifiers, file names, etc. */ 23: #define MAXFILE 15 24: #define MAXLINE 121 25: #define MAXNUM 7 26: 27: #define ID 1 /* return codes to indicate what is new on input line */ 28: #define NEWFILE 2 29: #define LINE 3 30: #define ERROR 4 31: 32: #define WIDTH 80 /* default line output width */ 33: 34: int width = WIDTH; 35: 36: char prev_id[MAXID] = ""; 37: char prev_file[MAXFILE] = ""; 38: 39: char id[MAXID] = ""; 40: char file[MAXFILE] = ""; 41: char line[MAXNUM] = ""; 42: 43: char *name; 44: char *basename(); /* strips leading path name */ 45: 46: main(argc, argv) 47: int argc; 48: char **argv; 49: { 50: char inline[BUFSIZ]; 51: char *gets(); 52: int val; 53: 54: name = basename(argv[0]); 55: 56: /* 57: * since this program is ONLY called by the cxref driver, 58: * we know that it will be called "fmtxref -w width" 59: * so we don't have to do complicated argument parsing. 60: * we also know that cxref makes sure we get a valid width. 61: */ 62: 63: if (argc > 1) 64: if (argc == 3) 65: if (strcmp(argv[1], "-w") == 0) 66: width = atoi(argv[2]); 67: else 68: usage(); 69: else 70: usage(); 71: /* else 72: use default width */ 73: 74: if(gets(inline) == NULL) 75: { 76: fprintf(stderr, "%s: standard input is empty.\n", name); 77: exit(1); 78: } 79: 80: if((val = breakup(inline)) == ERROR) 81: { 82: fprintf(stderr, "%s: malformed input '%s'\n", name, inline); 83: exit(2); 84: } 85: 86: output(val); /* does proper formatting */ 87: 88: while(gets(inline) != NULL && val != ERROR) 89: { 90: val = breakup(inline); 91: output(val); 92: } 93: 94: if(val == ERROR) 95: { 96: fprintf(stderr, "%s: malformed input '%s'\n", name, inline); 97: exit(2); 98: } 99: 100: putchar('\n'); 101: } 102: 103: breakup(text) 104: char *text; 105: { 106: int retval; 107: int i, j; 108: 109: if(text[0] == '"' || text[0] == '\'') 110: { 111: /* quoted stuff, break the line up by hand */ 112: 113: i = 0; 114: id[i++] = text[0]; 115: 116: for(j = 1; text[j] != text[0]; i++, j++) 117: { 118: id[i] = text[j]; 119: if(id[i] == '\\') 120: id[++i] = text[++j]; /* e.g. \" */ 121: } 122: id[i++] = text[0]; 123: id[i] = '\0'; 124: j++; /* skip close quote */ 125: 126: while(isspace(text[j])) 127: j++; 128: 129: for(i = 0; !isspace(text[j]); i++, j++) 130: file[i] = text[j]; 131: file[i] = '\0'; 132: 133: 134: while(isspace(text[j])) 135: j++; 136: 137: for(i = 0; !isspace(text[j]) && text[j] != '\0'; i++, j++) 138: line[i] = text[j]; 139: line[i] = '\0'; 140: } 141: else 142: { 143: if(sscanf(text, "%s %s %s", id, file, line) != 3) 144: return(ERROR); 145: } 146: 147: /* now decide about return code for formatting */ 148: 149: if(strcmp(prev_id, id) != 0) /* different identifiers */ 150: { 151: strcpy(prev_id, id); 152: strcpy(prev_file, file); 153: retval = ID; 154: } 155: else if(strcmp(prev_file, file) != 0) /* different files */ 156: { 157: strcpy(prev_file, file); 158: retval = NEWFILE; 159: } 160: else 161: retval = LINE; 162: 163: return(retval); 164: } 165: 166: output(val) 167: int val; 168: { 169: static int curpos = 1; 170: static int first = TRUE; 171: int line_len = strlen(line); 172: 173: switch(val) { 174: case ID: 175: if(! first) 176: putchar('\n'); /* finish off last line of prev id */ 177: else 178: first = FALSE; 179: 180: printf("%-20.20s\t%-14.14s\t%s", id, file, line); 181: curpos = 40 + line_len; 182: break; 183: 184: case NEWFILE: 185: printf("\n\t\t\t%-14.14s\t%s", file, line); 186: curpos = 40 + line_len; 187: break; 188: 189: case LINE: 190: if(curpos + line_len + 2 < width) 191: { 192: printf(", %s", line); /* same output line */ 193: curpos += 2 + line_len; 194: } 195: else 196: { 197: printf(",\n\t\t\t\t\t%s", line); /* new line */ 198: curpos = 40 + line_len; 199: } 200: break; 201: 202: case ERROR: 203: /* shouldn't come to here */ 204: fprintf(stderr, "%s: internal error: output() called with %s\n", 205: name, "a value of ERROR"); 206: fprintf(stderr, "%s: id == '%s'\tfile == '%s'\tline == '%s'\n", 207: name, id, file, line); 208: break; 209: 210: default: 211: /* shouldn't come to here either */ 212: fprintf(stderr, "%s: internal error: output() called with %s %d\n", 213: name, "the unknown value", val); 214: fprintf(stderr, "%s: id == '%s'\tfile == '%s'\tline == '%s'\n", 215: name, id, file, line); 216: break; 217: } 218: } 219: 220: usage() 221: { 222: char *basename(); 223: 224: fprintf(stderr, "usage: %s [-w width]\n", basename(name)); 225: exit (1); 226: } 227: 228: #include "basename.c"