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.1 (Berkeley) 06/05/85"; 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.symXXXX"; 60 LOCAL char *strname = "/tmp/obj.strXXXX"; 61 LOCAL char *filesname = "/tmp/obj.filesXXXX"; 62 LOCAL char *linesname = "/tmp/obj.linesXXXX"; 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 /* 74 * create temporary files for the namelist info 75 */ 76 77 startnlfile() 78 { 79 nlsize = 0; 80 (void) mktemp(symname); 81 (void) mktemp(strname); 82 (void) mktemp(filesname); 83 (void) mktemp(linesname); 84 symfp = fopen(symname, "w"); 85 strfp = fopen(strname, "w"); 86 filesfp = fopen(filesname, "w"); 87 linesfp = fopen(linesname, "w"); 88 if (symfp==NULL || strfp==NULL || filesfp==NULL || linesfp==NULL) { 89 fprintf(stderr, "can't create /tmp/obj"); 90 pexit(NOSTART); 91 } 92 newfile(filename, 1); 93 } 94 95 /* 96 * now copy the temp files back to obj; strings, symbols, file names, and lines 97 * 98 * There's some efficiency garbage here that uses straight system 99 * calls rather than standard I/O library calls. 100 */ 101 102 copynlfile() 103 { 104 register int n; 105 extern long lseek(); 106 int symfd, strfd, filesfd, linesfd; 107 char buff[BUFSIZ]; 108 109 (void) fclose((FILE *) symfp); 110 (void) fclose((FILE *) strfp); 111 (void) fclose((FILE *) filesfp); 112 (void) fclose((FILE *) linesfp); 113 if (!opt('g')) { 114 removenlfile(); 115 return; 116 } 117 symfd = open(symname, 0); 118 strfd = open(strname, 0); 119 filesfd = open(filesname, 0); 120 linesfd = open(linesname, 0); 121 if (symfd < 0 || strfd < 0 || filesfd < 0 || linesfd < 0) { 122 fprintf(stderr, "sync error on /tmp/obj"); 123 pexit(ERRS); 124 } 125 (void) lseek(ofil, 0L, 2); 126 write(ofil, (char *) (&nlhdr), sizeof(nlhdr)); 127 n = read(strfd, buff, BUFSIZ - sizeof(nlhdr)); 128 write(ofil, buff, n); 129 cat(strfd); 130 cat(symfd); 131 cat(filesfd); 132 cat(linesfd); 133 removenlfile(); 134 } 135 136 cat(fd) 137 int fd; 138 { 139 register int n; 140 char buff[BUFSIZ]; 141 142 while ((n = read(fd, buff, BUFSIZ)) > 0) { 143 write(ofil, buff, n); 144 } 145 (void) close(fd); 146 } 147 148 removenlfile() 149 { 150 unlink(symname); 151 unlink(strname); 152 unlink(filesname); 153 unlink(linesname); 154 } 155 156 nlhdrsize() 157 { 158 int r; 159 160 if (!opt('g')) { 161 r = 0; 162 } else { 163 r = nlsize + sizeof(nlhdr); 164 } 165 return r; 166 } 167 168 #define isblock(s) (s->class == FUNC || s->class == PROC) 169 #define isbuiltin(s) ((s->nl_block&037) == 0 && isblock(s)) 170 #define symno(p) (p==NULL ? 0 : nloff(p)) 171 172 struct nls { 173 struct nl *nls_low; 174 struct nl *nls_high; 175 }; 176 177 struct nl nl[], *nlp, ntab[], *nlact; 178 179 /*VARARGS*/ 180 savenl(to, rout) 181 struct nl *to; 182 { 183 register struct nl *p; 184 register OBJSYM *s; 185 OBJSYM tmpsym; 186 struct nls *nlsp; 187 188 if (to != NIL) { 189 putblock((char *) rout); 190 } else { 191 putblock("main program"); 192 } 193 nlsp = (struct nls *) nlact; 194 s = &tmpsym; 195 for (p = nlp; p != to;) { 196 if (p == nlsp->nls_low) { 197 if (nlsp == ((struct nls *) &ntab[0])) 198 break; 199 nlsp--; 200 p = nlsp->nls_high; 201 } 202 p--; 203 if (isbuiltin(p) || symno(p) == 0) { 204 continue; 205 } 206 nlhdr.nsyms++; 207 nlsize += sizeof(OBJSYM) + sizeof(int); 208 (void) putw(symno(p), symfp); 209 if (p->symbol != NULL) { 210 s->strindex = nlhdr.stringsize; 211 putstring(p->symbol); 212 } else { 213 s->strindex = 0; 214 } 215 s->oclass = p->class; 216 s->oblkno = (p->nl_block&037); 217 s->typno = symno(p->type); 218 s->chno = symno(p->chain); 219 s->osymvalue.orangev.lower = p->range[0]; 220 s->osymvalue.orangev.upper = p->range[1]; 221 if (isblock(p)) { 222 s->osymvalue.ofuncv.codeloc = p->value[NL_ENTLOC]; 223 } else if (p->class == RECORD || p->class == VARNT) { 224 s->osymvalue.ovarnt.vtorecno = symno(p->ptr[2]); 225 s->osymvalue.ovarnt.vtagno = symno(p->ptr[3]); 226 } 227 fwrite((char *) s, sizeof(*s), 1, symfp); 228 } 229 } 230 231 /* 232 * Dump a line number and the current object location counter. 233 * 234 * To save space the difference from the previous line number and offset 235 * (one byte each) is dumped. 236 */ 237 238 LOCAL int oline = 0; 239 LOCAL int olc = HEADER_BYTES; 240 241 lineno(line) 242 int line; 243 { 244 OBJLINE info; 245 246 if (line != oline) { 247 nlhdr.nlines++; 248 nlsize += sizeof(OBJLINE); 249 info.separate.lineincr = line - oline; 250 info.separate.addrincr = ((unsigned short) (lc - olc)); 251 (void) putw((int) info.together, linesfp); 252 oline = line; 253 olc = (int) lc; 254 } 255 } 256 257 /* 258 * put out a file name entry, including: 259 * 260 * the current line number for the new file 261 * the current location counter 262 * the string table address of the file name 263 * an index into the current line number information 264 */ 265 266 newfile(s, line) 267 char *s; 268 int line; 269 { 270 FILETAB ft; 271 272 nlhdr.nfiles++; 273 nlsize += sizeof(FILETAB); 274 ft.line = line; 275 oline = line; 276 if (lc == 0) { 277 ft.addr = 0; 278 } else { 279 ft.addr = ((LINENO) lc - HEADER_BYTES ); 280 } 281 ft.filename = (char *) nlhdr.stringsize; 282 putstring(s); 283 ft.lineindex = nlhdr.nlines; 284 fwrite((char *) (&ft), sizeof(ft), 1, filesfp); 285 } 286 287 /* 288 * put out a dummy symbol at the beginning of a block 289 */ 290 291 LOCAL putblock(s) 292 char *s; 293 { 294 static OBJSYM zerosym; 295 296 nlhdr.nsyms++; 297 nlsize += sizeof(OBJSYM) + sizeof(int); 298 (void) putw(0, symfp); 299 zerosym.strindex = nlhdr.stringsize; 300 putstring(s); 301 fwrite((char *) (&zerosym), sizeof(zerosym), 1, symfp); 302 } 303 304 /* 305 * put out a string to the string table file 306 */ 307 308 LOCAL putstring(s) 309 char *s; 310 { 311 register char *p; 312 313 for (p = s; *p != '\0'; p++) { 314 putc(*p, strfp); 315 } 316 nlhdr.stringsize += (p - s + 1); 317 nlsize += (p - s + 1); 318 putc('\0', strfp); 319 } 320 #endif OBJ 321