1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)savenl.c 1.1 01/18/82"; 4 5 /* 6 * savenl - routines for saving namelist and line number information 7 * 8 * This module contains the routines that make pi dump a namelist 9 * at the end of the object file. We do this by first creating 10 * four temporary files in "startnlfile". One temp file contains 11 * the string table, one the symbol table, one the file name 12 * information and one the line number information. 13 * 14 * Prior to generation of the code for a statement the "lineno" 15 * routine is called to dump the line number and current object 16 * address. At the end of each block "savenl" is called to dump 17 * the strings and symbol structures. 18 * 19 * At the end of execution "copynlfile" is called and it copies 20 * the temp files onto the end of the obj file. 21 * 22 * In case of error, "removenlfile" is called to destroy the temp files. 23 * 24 * The only other changes to pi are in calling these routines from 25 * 26 * "main" (main.c) 27 * "yymain" (yymain.c) 28 * "funcend" (fend.c) 29 * "yyget" (yyget.c) 30 * "putline" (stat.c) 31 */ 32 33 #include "whoami.h" 34 #include "0.h" 35 36 #undef NIL 37 38 /* 39 * pdx header files 40 */ 41 42 #include "defs.h" 43 #include "object.h" 44 #include "object/objsym.rep" 45 #include "mappings.h" 46 #include "mappings/filetab.h" 47 48 LOCAL char *symname = "/tmp/obj.symXXXX"; 49 LOCAL char *strname = "/tmp/obj.strXXXX"; 50 LOCAL char *filesname = "/tmp/obj.filesXXXX"; 51 LOCAL char *linesname = "/tmp/obj.linesXXXX"; 52 53 LOCAL FILE *symfp; 54 LOCAL FILE *strfp; 55 LOCAL FILE *filesfp; 56 LOCAL FILE *linesfp; 57 58 /* 59 * create temporary files for the namelist info 60 */ 61 62 startnlfile() 63 { 64 mktemp(symname); 65 mktemp(strname); 66 mktemp(filesname); 67 mktemp(linesname); 68 symfp = fopen(symname, "w"); 69 strfp = fopen(strname, "w"); 70 filesfp = fopen(filesname, "w"); 71 linesfp = fopen(linesname, "w"); 72 if (symfp==NULL || strfp==NULL || filesfp==NULL || linesfp==NULL) { 73 fprintf(stderr, "can't create /tmp/obj"); 74 pexit(NOSTART); 75 } 76 newfile(filename, 1); 77 } 78 79 /* 80 * now copy the temp files back to obj; strings, symbols, file names, and lines 81 * 82 * There's some efficiency garbage here that uses straight system 83 * calls rather than standard I/O library calls. 84 */ 85 86 copynlfile() 87 { 88 register int n; 89 int symfd, strfd, filesfd, linesfd; 90 char buff[BUFSIZ]; 91 92 fclose(symfp); 93 fclose(strfp); 94 fclose(filesfp); 95 fclose(linesfp); 96 symfd = open(symname, 0); 97 strfd = open(strname, 0); 98 filesfd = open(filesname, 0); 99 linesfd = open(linesname, 0); 100 if (symfd < 0 || strfd < 0 || filesfd < 0 || linesfd < 0) { 101 fprintf(stderr, "sync error on /tmp/obj"); 102 pexit(ERRS); 103 } 104 lseek(ofil, 0L, 2); 105 write(ofil, &nlhdr, sizeof(nlhdr)); 106 n = read(strfd, buff, BUFSIZ - sizeof(nlhdr)); 107 write(ofil, buff, n); 108 cat(strfd); 109 cat(symfd); 110 cat(filesfd); 111 cat(linesfd); 112 removenlfile(); 113 } 114 115 cat(fd) 116 int fd; 117 { 118 register int n; 119 char buff[BUFSIZ]; 120 121 while ((n = read(fd, buff, BUFSIZ)) > 0) { 122 write(ofil, buff, n); 123 } 124 close(fd); 125 } 126 127 removenlfile() 128 { 129 unlink(symname); 130 unlink(strname); 131 unlink(filesname); 132 unlink(linesname); 133 } 134 135 #define isblock(s) (s->class == FUNC || s->class == PROC) 136 #define isbuiltin(s) ((s->nl_block&037) == 0 && isblock(s)) 137 #define symno(p) (p==NULL ? 0 : nloff(p)) 138 139 struct nls { 140 struct nl *nls_low; 141 struct nl *nls_high; 142 }; 143 144 struct nl nl[], *nlp, ntab[], *nlact; 145 146 savenl(to, rout) 147 struct nl *to; 148 { 149 register struct nl *p; 150 register OBJSYM *s; 151 OBJSYM tmpsym; 152 struct nls *nlsp; 153 int v; 154 155 if (to != NIL) { 156 putblock(rout); 157 } else { 158 putblock("main program"); 159 } 160 nlsp = nlact; 161 s = &tmpsym; 162 for (p = nlp; p != to;) { 163 if (p == nlsp->nls_low) { 164 if (nlsp == &ntab[0]) 165 break; 166 nlsp--; 167 p = nlsp->nls_high; 168 } 169 p--; 170 if (isbuiltin(p) || symno(p) == 0) { 171 continue; 172 } 173 nlhdr.nsyms++; 174 putw(symno(p), symfp); 175 if (p->symbol != NULL) { 176 s->strindex = nlhdr.stringsize; 177 putstring(p->symbol); 178 } else { 179 s->strindex = 0; 180 } 181 s->oclass = p->class; 182 s->oblkno = (p->nl_block&037); 183 s->typno = symno(p->type); 184 s->chno = symno(p->chain); 185 s->osymvalue.orangev.lower = p->range[0]; 186 s->osymvalue.orangev.upper = p->range[1]; 187 if (isblock(p)) { 188 s->osymvalue.ofuncv.codeloc = p->entloc; 189 } else if (p->class == RECORD || p->class == VARNT) { 190 s->osymvalue.ovarnt.vtorecno = symno(p->ptr[2]); 191 s->osymvalue.ovarnt.vtagno = symno(p->ptr[3]); 192 } 193 fwrite(s, sizeof(*s), 1, symfp); 194 } 195 } 196 197 /* 198 * Dump a line number and the current object location counter. 199 * 200 * To save space the difference from the previous line number and offset 201 * (one byte each) is dumped. 202 */ 203 204 LOCAL int oline = 0; 205 LOCAL int olc = BASEADDR; 206 207 lineno(line) 208 int line; 209 { 210 if (line != oline) { 211 nlhdr.nlines++; 212 putc(line - oline, linesfp); 213 putc(lc - olc, linesfp); 214 oline = line; 215 olc = lc; 216 } 217 } 218 219 /* 220 * put out a file name entry, including: 221 * 222 * the current line number for the new file 223 * the current location counter 224 * the string table address of the file name 225 * an index into the current line number information 226 */ 227 228 newfile(s, line) 229 char *s; 230 int line; 231 { 232 FILETAB ft; 233 234 nlhdr.nfiles++; 235 ft.line = line; 236 oline = line; 237 if (lc == 0) { 238 ft.addr = 0; 239 } else { 240 ft.addr = lc - BASEADDR; 241 } 242 ft.filename = (char *) nlhdr.stringsize; 243 putstring(s); 244 ft.lineindex = nlhdr.nlines; 245 fwrite(&ft, sizeof(ft), 1, filesfp); 246 } 247 248 /* 249 * put out a dummy symbol at the beginning of a block 250 */ 251 252 LOCAL putblock(s) 253 char *s; 254 { 255 register int i; 256 static OBJSYM zerosym; 257 258 nlhdr.nsyms++; 259 putw(0, symfp); 260 zerosym.strindex = nlhdr.stringsize; 261 putstring(s); 262 fwrite(&zerosym, sizeof(zerosym), 1, symfp); 263 } 264 265 /* 266 * put out a string to the string table file 267 */ 268 269 LOCAL putstring(s) 270 char *s; 271 { 272 register char *p; 273 274 for (p = s; *p != '\0'; p++) 275 putc(*p, strfp); 276 nlhdr.stringsize += (p - s + 1); 277 putc('\0', strfp); 278 } 279