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