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