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