1 /* Copyright (c) 1984 Regents of the University of California */ 2 3 #ifndef lint 4 static char sccsid[] = "@(#)main.c 1.4 (Berkeley) 08/20/84"; 5 #endif not lint 6 7 #include <stdio.h> 8 #include <ctype.h> 9 #include "inline.h" 10 11 /* 12 * These are the pattern tables to be loaded 13 */ 14 struct pats *inittables[] = { 15 language_ptab, 16 libc_ptab, 17 machine_ptab, 18 0 19 }; 20 21 main(argc, argv) 22 int argc; 23 char *argv[]; 24 { 25 register char *cp, *lp; 26 register char *bufp; 27 register struct pats *pp, **php; 28 struct pats **tablep; 29 register struct inststoptbl *itp, **ithp; 30 int size; 31 extern char *index(); 32 33 if (argc > 1) 34 freopen(argv[1], "r", stdin); 35 if (argc > 2) 36 freopen(argv[2], "w", stdout); 37 /* 38 * Set up the hash table for the patterns. 39 */ 40 for (tablep = inittables; *tablep; tablep++) { 41 for (pp = *tablep; pp->name[0] != '\0'; pp++) { 42 php = &patshdr[hash(pp->name, &size)]; 43 pp->size = size; 44 pp->next = *php; 45 *php = pp; 46 } 47 } 48 /* 49 * Set up the hash table for the instruction stop table. 50 */ 51 for (itp = inststoptable; itp->name[0] != '\0'; itp++) { 52 ithp = &inststoptblhdr[hash(itp->name, &size)]; 53 itp->size = size; 54 itp->next = *ithp; 55 *ithp = itp; 56 } 57 /* 58 * check each line and replace as appropriate 59 */ 60 buftail = bufhead = 0; 61 bufp = line[0]; 62 while (fgets(bufp, MAXLINELEN, stdin)) { 63 lp = index(bufp, LABELCHAR); 64 if (lp != NULL) { 65 bufp = newline(); 66 if (*++lp == '\n') { 67 emptyqueue(); 68 continue; 69 } 70 strcpy(bufp, lp); 71 *lp++ = '\n'; 72 *lp = '\0'; 73 emptyqueue(); 74 } 75 for (cp = bufp; isspace(*cp); cp++) 76 /* void */; 77 if ((cp = doreplaceon(cp)) == 0) { 78 bufp = newline(); 79 continue; 80 } 81 for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) { 82 if (pp->size == size && bcmp(pp->name, cp, size) == 0) { 83 expand(pp->replace); 84 bufp = line[bufhead]; 85 break; 86 } 87 } 88 if (!pp) { 89 emptyqueue(); 90 fputs(bufp, stdout); 91 } 92 } 93 emptyqueue(); 94 exit(0); 95 } 96 97 /* 98 * Integrate an expansion into the assembly stream 99 */ 100 expand(replace) 101 char *replace; 102 { 103 register int curptr; 104 char *nextreplace, *argv[MAXARGS]; 105 int argc, argreg, foundarg, mod = 0; 106 char parsebuf[BUFSIZ]; 107 108 for (curptr = bufhead; curptr != buftail; ) { 109 nextreplace = copyline(replace, line[bufhead]); 110 argc = parseline(line[bufhead], argv, parsebuf); 111 argreg = nextarg(argc, argv); 112 if (argreg == -1) 113 break; 114 for (foundarg = 0; curptr != buftail; ) { 115 curptr = PRED(curptr); 116 argc = parseline(line[curptr], argv, parsebuf); 117 if (isendofblock(argc, argv)) 118 break; 119 if (foundarg = ispusharg(argc, argv)) 120 break; 121 mod |= 1 << modifies(argc, argv); 122 } 123 if (!foundarg) 124 break; 125 replace = nextreplace; 126 if (mod & (1 << argreg)) { 127 if (curptr == buftail) { 128 (void)newline(); 129 break; 130 } 131 (void)newline(); 132 } else { 133 rewrite(line[curptr], argc, argv, argreg); 134 mod |= 1 << argreg; 135 } 136 } 137 emptyqueue(); 138 fputs(replace, stdout); 139 } 140 141 /* 142 * Parse a line of assembly language into opcode and arguments. 143 */ 144 parseline(linep, argv, linebuf) 145 char *linep; 146 char *argv[]; 147 char *linebuf; 148 { 149 register char *bufp = linebuf, *cp = linep; 150 register int argc = 0; 151 152 for (;;) { 153 /* 154 * skip over white space 155 */ 156 while (isspace(*cp)) 157 cp++; 158 if (*cp == '\0') 159 return (argc); 160 /* 161 * copy argument 162 */ 163 if (argc == MAXARGS - 1) { 164 fprintf(stderr, "instruction too long->%s", linep); 165 return (argc); 166 } 167 argv[argc++] = bufp; 168 while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR) 169 *bufp++ = *cp++; 170 *bufp++ = '\0'; 171 if (*cp == COMMENTCHAR) 172 return (argc); 173 if (*cp == ARGSEPCHAR) 174 cp++; 175 } 176 } 177 178 /* 179 * Check for instructions that end a basic block. 180 */ 181 isendofblock(argc, argv) 182 int argc; 183 char *argv[]; 184 { 185 register struct inststoptbl *itp; 186 int size; 187 188 if (argc == 0) 189 return (0); 190 for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next) 191 if (itp->size == size && bcmp(argv[0], itp->name, size) == 0) 192 return (1); 193 return (0); 194 } 195 196 /* 197 * Copy a newline terminated string. 198 * Return pointer to character following last character copied. 199 */ 200 char * 201 copyline(from, to) 202 register char *from, *to; 203 { 204 205 while (*from != '\n') 206 *to++ = *from++; 207 *to++ = *from++; 208 *to = '\0'; 209 return (from); 210 } 211 212 /* 213 * open space for next line in the queue 214 */ 215 char * 216 newline() 217 { 218 bufhead = SUCC(bufhead); 219 if (bufhead == buftail) { 220 fputs(line[buftail], stdout); 221 buftail = SUCC(buftail); 222 } 223 return (line[bufhead]); 224 } 225 226 /* 227 * empty the queue by printing out all its lines. 228 */ 229 emptyqueue() 230 { 231 while (buftail != bufhead) { 232 fputs(line[buftail], stdout); 233 buftail = SUCC(buftail); 234 } 235 } 236 237 /* 238 * Compute the hash of a string. 239 * Return the hash and the size of the item hashed 240 */ 241 hash(cp, size) 242 char *cp; 243 int *size; 244 { 245 register char *cp1 = cp; 246 register int hash = 0; 247 248 while (*cp1 && *cp1 != '\n') 249 hash += (int)*cp1++; 250 *size = cp1 - cp + 1; 251 hash &= HSHSIZ - 1; 252 return (hash); 253 } 254