1: # include <stdio.h> 2: # include "constants.h" 3: # include "globals.h" 4: # include <sccs.h> 5: 6: SCCSID(@(#)include.c 8.1 12/31/84) 7: 8: 9: 10: /* 11: ** TST_INCLUDE -- Test and process a "#include" line 12: ** 13: ** Checks that a line is of the form '# include "<filename.q.h>"', 14: ** and calls include to change i/o files if so. 15: ** 16: ** Returns: 17: ** 1 -- if change of file was done 18: ** 0 -- otherwise 19: */ 20: 21: 22: tst_include() 23: { 24: register char *lp, *tp, *chp; 25: char temp [MAXSTRING + 1]; 26: 27: /* copy line read into temp ( because temp is same 28: * size as Linebuf, no overflow check is needed 29: */ 30: for (tp = temp, lp = Line_buf; (*tp++ = *lp++) != '\n'; ) 31: ; 32: /* skip white space between "#" and "include" */ 33: for (tp = &temp [1]; *tp == ' ' || *tp == '\t'; tp++) 34: ; 35: if (scompare("include", 7, tp, 7)) 36: return (0); 37: /* skip "include", the white space till '"' */ 38: for (tp = &tp [7]; *tp == ' ' || *tp == '\t'; tp++) 39: ; 40: if (*tp++ != '"') 41: return (0); 42: 43: /* {tp points to X in a line "#<white>include<white>"X..." } 44: * make "lp" point at right end '"' (filename must not have 45: * escaped '"' in it 46: */ 47: for (lp = tp; *lp != '"' && *lp != '\n'; lp++) 48: ; 49: 50: if (*lp != '"') 51: return (0); 52: /* make sure filename is long enough to have the equel "include" 53: * suffix ".q.h" 54: */ 55: if (lp - tp < 4) 56: return (0); 57: if (scompare(".q.h", 4, &lp [-4], 4)) 58: return (0); /* other include (non-equel) */ 59: 60: /* "chp" points at 'q' in '.q.h' which will be changed to 'c' */ 61: chp = &lp [-3]; 62: 63: /* check that rest of the line is white space */ 64: for (lp++; *lp == ' ' || *lp == '\t'; lp++) 65: ; 66: if (*lp != '\n') 67: { 68: *lp = '\0'; 69: yysemerr("garbage after valid \"#include\"", temp); 70: return (0); 71: } 72: *++lp = '\0'; 73: return (include(temp, tp, chp, &chp [3])); 74: } 75: /* 76: ** INCLUDE -- Change i/o files for a file inclusion 77: ** Saves status of current i/o files, puts out 78: ** '#include"___.c.h"', and opens appropriate files. 79: ** Makes both files legal C files, closing quotes, 80: ** and reopeneing them in the new file, if necessary. 81: ** 82: ** Parameters: 83: ** buf -- "#include..." line 84: ** start -- start of filename 85: ** chp -- *chp is 'q' in ".q.h" of filename 86: ** end -- ptr to last '"' after filename 87: ** 88: ** Returns: 89: ** 1 -- if i/o files changed 90: ** 0 -- otherwise 91: ** 92: ** Called By: 93: ** tst_include() -- [include.c] on seeing a pre-processor 94: ** line. 95: */ 96: 97: 98: include(buf, start, chp, end) 99: char *buf; 100: char *start; 101: char *chp; 102: char *end; 103: { 104: char in_q_flag; 105: register struct inc_file *i_f; 106: char *salloc(); 107: 108: in_q_flag = In_quote; 109: if (in_q_flag) 110: { 111: end_quote(); 112: equate_lines(); 113: } 114: 115: if (!(i_f = (struct inc_file *)nalloc(sizeof *i_f))) 116: { 117: err1 : 118: *++end = '\0'; /* overwrite before new-line at end */ 119: yysemerr("alloc error in #include processing", buf); 120: if (in_q_flag) 121: begin_quote(); 122: *end = '\n'; 123: return (0); 124: } 125: i_f->inc_yyline = yyline + 1; /* next line that will be read is 126: * yyline + 1 because getch does not 127: * see the '\n' at the end of the 128: * "#include" line 129: */ 130: i_f->inc_lineout = Lineout + 1; /* because the write of the "#include 131: * "... .c.h" file is done after the 132: * fixation of the value of Lineout. 133: */ 134: i_f->inc_fid = Input_file_name; 135: i_f->inc_outfile = Out_file; 136: i_f->inc_infile = In_file; 137: i_f->inc_next = 0; 138: 139: *end = '\0'; 140: if (!(Input_file_name = salloc(start))) 141: { 142: xfree(i_f); 143: goto err1; 144: } 145: 146: if ((In_file = fopen(Input_file_name, "r")) == NULL) 147: { 148: cant("read", Input_file_name); 149: err3 : 150: xfree(Input_file_name); 151: Input_file_name = i_f->inc_fid; 152: In_file = i_f->inc_infile; 153: xfree(i_f); 154: return (0); 155: } 156: *end = '"'; 157: *chp = 'c'; 158: 159: /* write out "#include..c.h" line (make sure it's at beginning 160: * of line. 161: */ 162: equate_lines(); 163: if (Charcnt != 0) 164: w_op("\n"); 165: w_op(buf); 166: fflush(Out_file); 167: *end = '\0'; 168: if ((Out_file = fopen(start, "w")) == NULL) 169: { 170: cant("write", start); 171: fclose(In_file); 172: Out_file = i_f->inc_outfile; 173: goto err3; 174: } 175: 176: /* go to it !!! */ 177: Lineout = yyline = Newline = 1; 178: Pre_proc_flg = 0; 179: Line_pos = 0; 180: if (in_q_flag) 181: begin_quote(); 182: Inc_files = i_f; 183: return (1); 184: } 185: /* 186: ** RESTOREF -- Restore previous file environment 187: ** Closes current files, and restores global variable 188: ** values for old files. 189: ** 190: ** Returns: 191: ** 0 -- if no old files (top level, no "#include"s) 192: ** 1 -- otherwise 193: ** 194: ** Called By: 195: ** equel() -- to close any files that may remain 196: ** open after a reset(III). 197: ** getch() -- upon receiving end-of-file 198: ** at some include level. 199: */ 200: 201: 202: restoref() 203: { 204: register struct inc_file *i_f; 205: 206: if (Inc_files) 207: { 208: fclose(Out_file); 209: fclose(In_file); 210: xfree(Input_file_name); 211: 212: /* restore previous environment */ 213: i_f = Inc_files; 214: yyline = i_f->inc_yyline; 215: Lineout = i_f->inc_lineout; 216: Input_file_name = i_f->inc_fid; 217: Out_file = i_f->inc_outfile; 218: In_file = i_f->inc_infile; 219: Line_pos = 0; 220: Inc_files = i_f->inc_next; 221: xfree(i_f); 222: return (1); 223: } 224: return (0); 225: }