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