1*8e2a856bSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*8e2a856bSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*8e2a856bSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*8e2a856bSAndrew Rist * distributed with this work for additional information 6*8e2a856bSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*8e2a856bSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*8e2a856bSAndrew Rist * "License"); you may not use this file except in compliance 9*8e2a856bSAndrew Rist * with the License. You may obtain a copy of the License at 10*8e2a856bSAndrew Rist * 11*8e2a856bSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*8e2a856bSAndrew Rist * 13*8e2a856bSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*8e2a856bSAndrew Rist * software distributed under the License is distributed on an 15*8e2a856bSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*8e2a856bSAndrew Rist * KIND, either express or implied. See the License for the 17*8e2a856bSAndrew Rist * specific language governing permissions and limitations 18*8e2a856bSAndrew Rist * under the License. 19*8e2a856bSAndrew Rist * 20*8e2a856bSAndrew Rist *************************************************************/ 21*8e2a856bSAndrew Rist 22*8e2a856bSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include <stdio.h> 25cdf0e10cSrcweir #include <ctype.h> 26cdf0e10cSrcweir #include "cppdef.h" 27cdf0e10cSrcweir #include "cpp.h" 28cdf0e10cSrcweir #if HOST == SYS_VMS 29cdf0e10cSrcweir /* 30cdf0e10cSrcweir * Include the rms stuff. (We can't just include rms.h as it uses the 31cdf0e10cSrcweir * VaxC-specific library include syntax that Decus CPP doesn't support. 32cdf0e10cSrcweir * By including things by hand, we can CPP ourself.) 33cdf0e10cSrcweir */ 34cdf0e10cSrcweir #include <nam.h> 35cdf0e10cSrcweir #include <fab.h> 36cdf0e10cSrcweir #include <rab.h> 37cdf0e10cSrcweir #include <rmsdef.h> 38cdf0e10cSrcweir #endif 39cdf0e10cSrcweir 40cdf0e10cSrcweir /* 41cdf0e10cSrcweir * Generate (by hand-inspection) a set of unique values for each control 42cdf0e10cSrcweir * operator. Note that this is not guaranteed to work for non-Ascii 43cdf0e10cSrcweir * machines. CPP won't compile if there are hash conflicts. 44cdf0e10cSrcweir */ 45cdf0e10cSrcweir 46cdf0e10cSrcweir #define L_assert ('a' + ('s' << 1)) 47cdf0e10cSrcweir #define L_define ('d' + ('f' << 1)) 48cdf0e10cSrcweir #define L_elif ('e' + ('i' << 1)) 49cdf0e10cSrcweir #define L_else ('e' + ('s' << 1)) 50cdf0e10cSrcweir #define L_endif ('e' + ('d' << 1)) 51cdf0e10cSrcweir #define L_if ('i' + (EOS << 1)) 52cdf0e10cSrcweir #define L_ifdef ('i' + ('d' << 1)) 53cdf0e10cSrcweir #define L_ifndef ('i' + ('n' << 1)) 54cdf0e10cSrcweir #define L_include ('i' + ('c' << 1)) 55cdf0e10cSrcweir #define L_line ('l' + ('n' << 1)) 56cdf0e10cSrcweir #define L_nogood (EOS + (EOS << 1)) /* To catch #i */ 57cdf0e10cSrcweir #define L_pragma ('p' + ('a' << 1)) 58cdf0e10cSrcweir #define L_undef ('u' + ('d' << 1)) 59cdf0e10cSrcweir #define L_error ('e' + ('r' << 1)) /* BP 5.3.92, #error */ 60cdf0e10cSrcweir #define MAXLINE 80 /* BP 5.3.92, #error */ 61cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 62cdf0e10cSrcweir #define L_debug ('d' + ('b' << 1)) /* #debug */ 63cdf0e10cSrcweir #define L_nodebug ('n' + ('d' << 1)) /* #nodebug */ 64cdf0e10cSrcweir #endif 65cdf0e10cSrcweir 66cdf0e10cSrcweir 67cdf0e10cSrcweir void InitCpp2() 68cdf0e10cSrcweir { 69cdf0e10cSrcweir 70cdf0e10cSrcweir } 71cdf0e10cSrcweir 72cdf0e10cSrcweir 73cdf0e10cSrcweir int 74cdf0e10cSrcweir control(int counter) 75cdf0e10cSrcweir /* 76cdf0e10cSrcweir * Process #control lines. Simple commands are processed inline, 77cdf0e10cSrcweir * while complex commands have their own subroutines. 78cdf0e10cSrcweir * 79cdf0e10cSrcweir * The counter is used to force out a newline before #line, and 80cdf0e10cSrcweir * #pragma commands. This prevents these commands from ending up at 81cdf0e10cSrcweir * the end of the previous line if cpp is invoked with the -C option. 82cdf0e10cSrcweir */ 83cdf0e10cSrcweir { 84cdf0e10cSrcweir register int c; 85cdf0e10cSrcweir register char *tp; 86cdf0e10cSrcweir register int hash; 87cdf0e10cSrcweir char *ep; 88cdf0e10cSrcweir 89cdf0e10cSrcweir c = skipws(); 90cdf0e10cSrcweir if (c == '\n' || c == EOF_CHAR) 91cdf0e10cSrcweir return (counter + 1); 92cdf0e10cSrcweir if (!isdigit(c)) 93cdf0e10cSrcweir scanid(c); /* Get #word to token[] */ 94cdf0e10cSrcweir else { 95cdf0e10cSrcweir unget(); /* Hack -- allow #123 as a */ 96cdf0e10cSrcweir strcpy(token, "line"); /* synonym for #line 123 */ 97cdf0e10cSrcweir } 98cdf0e10cSrcweir hash = (token[1] == EOS) ? L_nogood : (token[0] + (token[2] << 1)); 99cdf0e10cSrcweir switch (hash) { 100cdf0e10cSrcweir case L_assert: tp = "assert"; break; 101cdf0e10cSrcweir case L_define: tp = "define"; break; 102cdf0e10cSrcweir case L_elif: tp = "elif"; break; 103cdf0e10cSrcweir case L_else: tp = "else"; break; 104cdf0e10cSrcweir case L_endif: tp = "endif"; break; 105cdf0e10cSrcweir case L_if: tp = "if"; break; 106cdf0e10cSrcweir case L_ifdef: tp = "ifdef"; break; 107cdf0e10cSrcweir case L_ifndef: tp = "ifndef"; break; 108cdf0e10cSrcweir case L_include: tp = "include"; break; 109cdf0e10cSrcweir case L_line: tp = "line"; break; 110cdf0e10cSrcweir case L_pragma: tp = "pragma"; break; 111cdf0e10cSrcweir case L_undef: tp = "undef"; break; 112cdf0e10cSrcweir case L_error: tp = "error"; break; 113cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 114cdf0e10cSrcweir case L_debug: tp = "debug"; break; 115cdf0e10cSrcweir case L_nodebug: tp = "nodebug"; break; 116cdf0e10cSrcweir #endif 117cdf0e10cSrcweir default: hash = L_nogood; 118cdf0e10cSrcweir case L_nogood: tp = ""; break; 119cdf0e10cSrcweir } 120cdf0e10cSrcweir if (!streq(tp, token)) 121cdf0e10cSrcweir hash = L_nogood; 122cdf0e10cSrcweir /* 123cdf0e10cSrcweir * hash is set to a unique value corresponding to the 124cdf0e10cSrcweir * control keyword (or L_nogood if we think it's nonsense). 125cdf0e10cSrcweir */ 126cdf0e10cSrcweir if (infile->fp == NULL) 127cdf0e10cSrcweir cwarn("Control line \"%s\" within macro expansion", token); 128cdf0e10cSrcweir if (!compiling) { /* Not compiling now */ 129cdf0e10cSrcweir switch (hash) { 130cdf0e10cSrcweir case L_if: /* These can't turn */ 131cdf0e10cSrcweir case L_ifdef: /* compilation on, but */ 132cdf0e10cSrcweir case L_ifndef: /* we must nest #if's */ 133cdf0e10cSrcweir if (++ifptr >= &ifstack[BLK_NEST]) 134cdf0e10cSrcweir goto if_nest_err; 135cdf0e10cSrcweir *ifptr = 0; /* !WAS_COMPILING */ 136cdf0e10cSrcweir case L_line: /* Many */ 137cdf0e10cSrcweir /* 138cdf0e10cSrcweir * Are pragma's always processed? 139cdf0e10cSrcweir */ 140cdf0e10cSrcweir case L_pragma: /* options */ 141cdf0e10cSrcweir case L_include: /* are uninteresting */ 142cdf0e10cSrcweir case L_define: /* if we */ 143cdf0e10cSrcweir case L_undef: /* aren't */ 144cdf0e10cSrcweir case L_assert: /* compiling. */ 145cdf0e10cSrcweir case L_error: /* BP 5.3.92, #error */ 146cdf0e10cSrcweir dump_line: skipnl(); /* Ignore rest of line */ 147cdf0e10cSrcweir return (counter + 1); 148cdf0e10cSrcweir } 149cdf0e10cSrcweir } 150cdf0e10cSrcweir /* 151cdf0e10cSrcweir * Make sure that #line and #pragma are output on a fresh line. 152cdf0e10cSrcweir */ 153cdf0e10cSrcweir if (counter > 0 && (hash == L_line || hash == L_pragma)) { 154cdf0e10cSrcweir PUTCHAR('\n'); 155cdf0e10cSrcweir counter--; 156cdf0e10cSrcweir } 157cdf0e10cSrcweir switch (hash) { 158cdf0e10cSrcweir case L_line: 159cdf0e10cSrcweir /* 160cdf0e10cSrcweir * Parse the line to update the line number and "progname" 161cdf0e10cSrcweir * field and line number for the next input line. 162cdf0e10cSrcweir * Set wrongline to force it out later. 163cdf0e10cSrcweir */ 164cdf0e10cSrcweir c = skipws(); 165cdf0e10cSrcweir workp = work; /* Save name in work */ 166cdf0e10cSrcweir while (c != '\n' && c != EOF_CHAR) { 167cdf0e10cSrcweir save(c); 168cdf0e10cSrcweir c = get(); 169cdf0e10cSrcweir } 170cdf0e10cSrcweir unget(); 171cdf0e10cSrcweir save(EOS); 172cdf0e10cSrcweir /* 173cdf0e10cSrcweir * Split #line argument into <line-number> and <name> 174cdf0e10cSrcweir * We subtract 1 as we want the number of the next line. 175cdf0e10cSrcweir */ 176cdf0e10cSrcweir line = atoi(work) - 1; /* Reset line number */ 177cdf0e10cSrcweir for (tp = work; isdigit(*tp) || type[(int)*tp] == SPA; tp++) 178cdf0e10cSrcweir ; /* Skip over digits */ 179cdf0e10cSrcweir if (*tp != EOS) { /* Got a filename, so: */ 180cdf0e10cSrcweir if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) { 181cdf0e10cSrcweir tp++; /* Skip over left quote */ 182cdf0e10cSrcweir *ep = EOS; /* And ignore right one */ 183cdf0e10cSrcweir } 184cdf0e10cSrcweir if (infile->progname != NULL) /* Give up the old name */ 185cdf0e10cSrcweir free(infile->progname); /* if it's allocated. */ 186cdf0e10cSrcweir infile->progname = savestring(tp); 187cdf0e10cSrcweir } 188cdf0e10cSrcweir wrongline = TRUE; /* Force output later */ 189cdf0e10cSrcweir break; 190cdf0e10cSrcweir 191cdf0e10cSrcweir case L_include: 192cdf0e10cSrcweir doinclude(); 193cdf0e10cSrcweir break; 194cdf0e10cSrcweir 195cdf0e10cSrcweir case L_define: 196cdf0e10cSrcweir dodefine(); 197cdf0e10cSrcweir break; 198cdf0e10cSrcweir 199cdf0e10cSrcweir case L_undef: 200cdf0e10cSrcweir doundef(); 201cdf0e10cSrcweir break; 202cdf0e10cSrcweir 203cdf0e10cSrcweir case L_else: 204cdf0e10cSrcweir if (ifptr == &ifstack[0]) 205cdf0e10cSrcweir goto nest_err; 206cdf0e10cSrcweir else if ((*ifptr & ELSE_SEEN) != 0) 207cdf0e10cSrcweir goto else_seen_err; 208cdf0e10cSrcweir *ifptr |= ELSE_SEEN; 209cdf0e10cSrcweir if ((*ifptr & WAS_COMPILING) != 0) { 210cdf0e10cSrcweir if (compiling || (*ifptr & TRUE_SEEN) != 0) 211cdf0e10cSrcweir compiling = FALSE; 212cdf0e10cSrcweir else { 213cdf0e10cSrcweir compiling = TRUE; 214cdf0e10cSrcweir } 215cdf0e10cSrcweir } 216cdf0e10cSrcweir break; 217cdf0e10cSrcweir 218cdf0e10cSrcweir case L_elif: 219cdf0e10cSrcweir if (ifptr == &ifstack[0]) 220cdf0e10cSrcweir goto nest_err; 221cdf0e10cSrcweir else if ((*ifptr & ELSE_SEEN) != 0) { 222cdf0e10cSrcweir else_seen_err: cerror("#%s may not follow #else", token); 223cdf0e10cSrcweir goto dump_line; 224cdf0e10cSrcweir } 225cdf0e10cSrcweir if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) { 226cdf0e10cSrcweir compiling = FALSE; /* Done compiling stuff */ 227cdf0e10cSrcweir goto dump_line; /* Skip this clause */ 228cdf0e10cSrcweir } 229cdf0e10cSrcweir doif(L_if); 230cdf0e10cSrcweir break; 231cdf0e10cSrcweir 232cdf0e10cSrcweir case L_if: 233cdf0e10cSrcweir case L_ifdef: 234cdf0e10cSrcweir case L_ifndef: 235cdf0e10cSrcweir if (++ifptr >= &ifstack[BLK_NEST]) 236cdf0e10cSrcweir if_nest_err: cfatal("Too many nested #%s statements", token); 237cdf0e10cSrcweir *ifptr = WAS_COMPILING; 238cdf0e10cSrcweir doif(hash); 239cdf0e10cSrcweir break; 240cdf0e10cSrcweir 241cdf0e10cSrcweir case L_endif: 242cdf0e10cSrcweir if (ifptr == &ifstack[0]) { 243cdf0e10cSrcweir nest_err: cerror("#%s must be in an #if", token); 244cdf0e10cSrcweir goto dump_line; 245cdf0e10cSrcweir } 246cdf0e10cSrcweir if (!compiling && (*ifptr & WAS_COMPILING) != 0) 247cdf0e10cSrcweir wrongline = TRUE; 248cdf0e10cSrcweir compiling = ((*ifptr & WAS_COMPILING) != 0); 249cdf0e10cSrcweir --ifptr; 250cdf0e10cSrcweir break; 251cdf0e10cSrcweir 252cdf0e10cSrcweir case L_assert: 253cdf0e10cSrcweir if (eval() == 0) 254cdf0e10cSrcweir cerror("Preprocessor assertion failure", NULLST); 255cdf0e10cSrcweir break; 256cdf0e10cSrcweir 257cdf0e10cSrcweir case L_pragma: 258cdf0e10cSrcweir /* 259cdf0e10cSrcweir * #pragma is provided to pass "options" to later 260cdf0e10cSrcweir * passes of the compiler. cpp doesn't have any yet. 261cdf0e10cSrcweir */ 262cdf0e10cSrcweir fprintf( pCppOut, "#pragma "); 263cdf0e10cSrcweir while ((c = get()) != '\n' && c != EOF_CHAR) 264cdf0e10cSrcweir cput(c); 265cdf0e10cSrcweir unget(); 266cdf0e10cSrcweir break; 267cdf0e10cSrcweir 268cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 269cdf0e10cSrcweir case L_debug: 270cdf0e10cSrcweir if (debug == 0) 271cdf0e10cSrcweir dumpdef("debug set on"); 272cdf0e10cSrcweir debug++; 273cdf0e10cSrcweir break; 274cdf0e10cSrcweir 275cdf0e10cSrcweir case L_nodebug: 276cdf0e10cSrcweir debug--; 277cdf0e10cSrcweir break; 278cdf0e10cSrcweir #endif 279cdf0e10cSrcweir case L_error: /* BP 5.3.92, #error */ 280cdf0e10cSrcweir { 281cdf0e10cSrcweir fprintf( pCppOut, "cpp: line %u, Error directive: ", line ); 282cdf0e10cSrcweir while ((c = get()) != '\n' && c != EOF_CHAR) 283cdf0e10cSrcweir cput(c); 284cdf0e10cSrcweir fprintf( pCppOut, "\n" ); 285cdf0e10cSrcweir exit( 1 ); 286cdf0e10cSrcweir break; 287cdf0e10cSrcweir } 288cdf0e10cSrcweir default: 289cdf0e10cSrcweir /* 290cdf0e10cSrcweir * Undefined #control keyword. 291cdf0e10cSrcweir * Note: the correct behavior may be to warn and 292cdf0e10cSrcweir * pass the line to a subsequent compiler pass. 293cdf0e10cSrcweir * This would allow #asm or similar extensions. 294cdf0e10cSrcweir */ 295cdf0e10cSrcweir cerror("Illegal # command \"%s\"", token); 296cdf0e10cSrcweir break; 297cdf0e10cSrcweir } 298cdf0e10cSrcweir if (hash != L_include) { 299cdf0e10cSrcweir #if OLD_PREPROCESSOR 300cdf0e10cSrcweir /* 301cdf0e10cSrcweir * Ignore the rest of the #control line so you can write 302cdf0e10cSrcweir * #if foo 303cdf0e10cSrcweir * #endif foo 304cdf0e10cSrcweir */ 305cdf0e10cSrcweir goto dump_line; /* Take common exit */ 306cdf0e10cSrcweir #else 307cdf0e10cSrcweir if (skipws() != '\n') { 308cdf0e10cSrcweir cwarn("Unexpected text in #control line ignored", NULLST); 309cdf0e10cSrcweir skipnl(); 310cdf0e10cSrcweir } 311cdf0e10cSrcweir #endif 312cdf0e10cSrcweir } 313cdf0e10cSrcweir return (counter + 1); 314cdf0e10cSrcweir } 315cdf0e10cSrcweir 316cdf0e10cSrcweir FILE_LOCAL 317cdf0e10cSrcweir void doif(int hash) 318cdf0e10cSrcweir /* 319cdf0e10cSrcweir * Process an #if, #ifdef, or #ifndef. The latter two are straightforward, 320cdf0e10cSrcweir * while #if needs a subroutine of its own to evaluate the expression. 321cdf0e10cSrcweir * 322cdf0e10cSrcweir * doif() is called only if compiling is TRUE. If false, compilation 323cdf0e10cSrcweir * is always supressed, so we don't need to evaluate anything. This 324cdf0e10cSrcweir * supresses unnecessary warnings. 325cdf0e10cSrcweir */ 326cdf0e10cSrcweir { 327cdf0e10cSrcweir register int c; 328cdf0e10cSrcweir register int found; 329cdf0e10cSrcweir 330cdf0e10cSrcweir if ((c = skipws()) == '\n' || c == EOF_CHAR) { 331cdf0e10cSrcweir unget(); 332cdf0e10cSrcweir goto badif; 333cdf0e10cSrcweir } 334cdf0e10cSrcweir if (hash == L_if) { 335cdf0e10cSrcweir unget(); 336cdf0e10cSrcweir found = (eval() != 0); /* Evaluate expr, != 0 is TRUE */ 337cdf0e10cSrcweir hash = L_ifdef; /* #if is now like #ifdef */ 338cdf0e10cSrcweir } 339cdf0e10cSrcweir else { 340cdf0e10cSrcweir if (type[c] != LET) /* Next non-blank isn't letter */ 341cdf0e10cSrcweir goto badif; /* ... is an error */ 342cdf0e10cSrcweir found = (lookid(c) != NULL); /* Look for it in symbol table */ 343cdf0e10cSrcweir } 344cdf0e10cSrcweir if (found == (hash == L_ifdef)) { 345cdf0e10cSrcweir compiling = TRUE; 346cdf0e10cSrcweir *ifptr |= TRUE_SEEN; 347cdf0e10cSrcweir } 348cdf0e10cSrcweir else { 349cdf0e10cSrcweir compiling = FALSE; 350cdf0e10cSrcweir } 351cdf0e10cSrcweir return; 352cdf0e10cSrcweir 353cdf0e10cSrcweir badif: cerror("#if, #ifdef, or #ifndef without an argument", NULLST); 354cdf0e10cSrcweir #if !OLD_PREPROCESSOR 355cdf0e10cSrcweir skipnl(); /* Prevent an extra */ 356cdf0e10cSrcweir unget(); /* Error message */ 357cdf0e10cSrcweir #endif 358cdf0e10cSrcweir return; 359cdf0e10cSrcweir } 360cdf0e10cSrcweir 361cdf0e10cSrcweir FILE_LOCAL 362cdf0e10cSrcweir void doinclude() 363cdf0e10cSrcweir /* 364cdf0e10cSrcweir * Process the #include control line. 365cdf0e10cSrcweir * There are three variations: 366cdf0e10cSrcweir * #include "file" search somewhere relative to the 367cdf0e10cSrcweir * current source file, if not found, 368cdf0e10cSrcweir * treat as #include <file>. 369cdf0e10cSrcweir * #include <file> Search in an implementation-dependent 370cdf0e10cSrcweir * list of places. 371cdf0e10cSrcweir * #include token Expand the token, it must be one of 372cdf0e10cSrcweir * "file" or <file>, process as such. 373cdf0e10cSrcweir * 374cdf0e10cSrcweir * Note: the November 12 draft forbids '>' in the #include <file> format. 375cdf0e10cSrcweir * This restriction is unnecessary and not implemented. 376cdf0e10cSrcweir */ 377cdf0e10cSrcweir { 378cdf0e10cSrcweir register int c; 379cdf0e10cSrcweir register int delim; 380cdf0e10cSrcweir #if HOST == SYS_VMS 381cdf0e10cSrcweir char def_filename[NAM$C_MAXRSS + 1]; 382cdf0e10cSrcweir #endif 383cdf0e10cSrcweir 384cdf0e10cSrcweir delim = macroid(skipws()); 385cdf0e10cSrcweir if (delim != '<' && delim != '"') 386cdf0e10cSrcweir goto incerr; 387cdf0e10cSrcweir if (delim == '<') 388cdf0e10cSrcweir delim = '>'; 389cdf0e10cSrcweir workp = work; 390cdf0e10cSrcweir instring = TRUE; /* Accept all characters */ 391cdf0e10cSrcweir #ifdef CONTROL_COMMENTS_NOT_ALLOWED 392cdf0e10cSrcweir while ((c = get()) != '\n' && c != EOF_CHAR) 393cdf0e10cSrcweir save(c); /* Put it away. */ 394cdf0e10cSrcweir unget(); /* Force nl after includee */ 395cdf0e10cSrcweir /* 396cdf0e10cSrcweir * The draft is unclear if the following should be done. 397cdf0e10cSrcweir */ 398cdf0e10cSrcweir while (--workp >= work && *workp == ' ') 399cdf0e10cSrcweir ; /* Trim blanks from filename */ 400cdf0e10cSrcweir if (*workp != delim) 401cdf0e10cSrcweir goto incerr; 402cdf0e10cSrcweir #else 403cdf0e10cSrcweir while ((c = get()) != delim && c != EOF_CHAR) 404cdf0e10cSrcweir save(c); 405cdf0e10cSrcweir #endif 406cdf0e10cSrcweir *workp = EOS; /* Terminate filename */ 407cdf0e10cSrcweir instring = FALSE; 408cdf0e10cSrcweir #if HOST == SYS_VMS 409cdf0e10cSrcweir /* 410cdf0e10cSrcweir * Assume the default .h filetype. 411cdf0e10cSrcweir */ 412cdf0e10cSrcweir if (!vmsparse(work, ".H", def_filename)) { 413cdf0e10cSrcweir perror(work); /* Oops. */ 414cdf0e10cSrcweir goto incerr; 415cdf0e10cSrcweir } 416cdf0e10cSrcweir else if (openinclude(def_filename, (delim == '"'))) 417cdf0e10cSrcweir return; 418cdf0e10cSrcweir #else 419cdf0e10cSrcweir if (openinclude(work, (delim == '"'))) 420cdf0e10cSrcweir return; 421cdf0e10cSrcweir #endif 422cdf0e10cSrcweir /* 423cdf0e10cSrcweir * No sense continuing if #include file isn't there. 424cdf0e10cSrcweir */ 425cdf0e10cSrcweir cfatal("Cannot open include file \"%s\"", work); 426cdf0e10cSrcweir 427cdf0e10cSrcweir incerr: cerror("#include syntax error", NULLST); 428cdf0e10cSrcweir return; 429cdf0e10cSrcweir } 430cdf0e10cSrcweir 431cdf0e10cSrcweir FILE_LOCAL int 432cdf0e10cSrcweir openinclude(char* filename, int searchlocal) 433cdf0e10cSrcweir /* 434cdf0e10cSrcweir * Actually open an include file. This routine is only called from 435cdf0e10cSrcweir * doinclude() above, but was written as a separate subroutine for 436cdf0e10cSrcweir * programmer convenience. It searches the list of directories 437cdf0e10cSrcweir * and actually opens the file, linking it into the list of 438cdf0e10cSrcweir * active files. Returns TRUE if the file was opened, FALSE 439cdf0e10cSrcweir * if openinclude() fails. No error message is printed. 440cdf0e10cSrcweir */ 441cdf0e10cSrcweir { 442cdf0e10cSrcweir register char **incptr; 443cdf0e10cSrcweir #if HOST == SYS_VMS 444cdf0e10cSrcweir #if NFWORK < (NAM$C_MAXRSS + 1) 445cdf0e10cSrcweir << error, NFWORK is not greater than NAM$C_MAXRSS >> 446cdf0e10cSrcweir #endif 447cdf0e10cSrcweir #endif 448cdf0e10cSrcweir char tmpname[NFWORK]; /* Filename work area */ 449cdf0e10cSrcweir 450cdf0e10cSrcweir if (searchlocal) { 451cdf0e10cSrcweir /* 452cdf0e10cSrcweir * Look in local directory first 453cdf0e10cSrcweir */ 454cdf0e10cSrcweir #if HOST == SYS_UNIX 455cdf0e10cSrcweir /* 456cdf0e10cSrcweir * Try to open filename relative to the directory of the current 457cdf0e10cSrcweir * source file (as opposed to the current directory). (ARF, SCK). 458cdf0e10cSrcweir */ 459cdf0e10cSrcweir if (filename[0] != '/' 460cdf0e10cSrcweir && hasdirectory(infile->filename, tmpname)) 461cdf0e10cSrcweir strcat(tmpname, filename); 462cdf0e10cSrcweir else { 463cdf0e10cSrcweir strcpy(tmpname, filename); 464cdf0e10cSrcweir } 465cdf0e10cSrcweir #else 466cdf0e10cSrcweir if (!hasdirectory(filename, tmpname) 467cdf0e10cSrcweir && hasdirectory(infile->filename, tmpname)) 468cdf0e10cSrcweir strcat(tmpname, filename); 469cdf0e10cSrcweir else { 470cdf0e10cSrcweir strcpy(tmpname, filename); 471cdf0e10cSrcweir } 472cdf0e10cSrcweir #endif 473cdf0e10cSrcweir if (openfile(tmpname)) 474cdf0e10cSrcweir return (TRUE); 475cdf0e10cSrcweir } 476cdf0e10cSrcweir /* 477cdf0e10cSrcweir * Look in any directories specified by -I command line 478cdf0e10cSrcweir * arguments, then in the builtin search list. 479cdf0e10cSrcweir */ 480cdf0e10cSrcweir for (incptr = incdir; incptr < incend; incptr++) { 481cdf0e10cSrcweir if (strlen(*incptr) + strlen(filename) >= (NFWORK - 1)) 482cdf0e10cSrcweir cfatal("Filename work buffer overflow", NULLST); 483cdf0e10cSrcweir else { 484cdf0e10cSrcweir #if HOST == SYS_UNIX 485cdf0e10cSrcweir if (filename[0] == '/') 486cdf0e10cSrcweir strcpy(tmpname, filename); 487cdf0e10cSrcweir else { 488cdf0e10cSrcweir sprintf(tmpname, "%s/%s", *incptr, filename); 489cdf0e10cSrcweir } 490cdf0e10cSrcweir #elif HOST == SYS_UNKNOWN 491cdf0e10cSrcweir if (filename[0] == '\\') 492cdf0e10cSrcweir strcpy(tmpname, filename); 493cdf0e10cSrcweir else { 494cdf0e10cSrcweir sprintf(tmpname, "%s\\%s", *incptr, filename); 495cdf0e10cSrcweir } 496cdf0e10cSrcweir #else 497cdf0e10cSrcweir if (!hasdirectory(filename, tmpname)) 498cdf0e10cSrcweir sprintf(tmpname, "%s%s", *incptr, filename); 499cdf0e10cSrcweir #endif 500cdf0e10cSrcweir if (openfile(tmpname)) 501cdf0e10cSrcweir return (TRUE); 502cdf0e10cSrcweir } 503cdf0e10cSrcweir } 504cdf0e10cSrcweir return (FALSE); 505cdf0e10cSrcweir } 506cdf0e10cSrcweir 507cdf0e10cSrcweir FILE_LOCAL int 508cdf0e10cSrcweir hasdirectory(char* source, char* result) 509cdf0e10cSrcweir /* 510cdf0e10cSrcweir * If a device or directory is found in the source filename string, the 511cdf0e10cSrcweir * node/device/directory part of the string is copied to result and 512cdf0e10cSrcweir * hasdirectory returns TRUE. Else, nothing is copied and it returns FALSE. 513cdf0e10cSrcweir */ 514cdf0e10cSrcweir { 515cdf0e10cSrcweir #if HOST == SYS_UNIX 516cdf0e10cSrcweir register char *tp; 517cdf0e10cSrcweir 518cdf0e10cSrcweir if ((tp = strrchr(source, '/')) == NULL) 519cdf0e10cSrcweir return (FALSE); 520cdf0e10cSrcweir else { 521cdf0e10cSrcweir strncpy(result, source, tp - source + 1); 522cdf0e10cSrcweir result[tp - source + 1] = EOS; 523cdf0e10cSrcweir return (TRUE); 524cdf0e10cSrcweir } 525cdf0e10cSrcweir #else 526cdf0e10cSrcweir #if HOST == SYS_VMS 527cdf0e10cSrcweir if (vmsparse(source, NULLST, result) 528cdf0e10cSrcweir && result[0] != EOS) 529cdf0e10cSrcweir return (TRUE); 530cdf0e10cSrcweir else { 531cdf0e10cSrcweir return (FALSE); 532cdf0e10cSrcweir } 533cdf0e10cSrcweir #else 534cdf0e10cSrcweir /* 535cdf0e10cSrcweir * Random DEC operating system (RSX, RT11, RSTS/E) 536cdf0e10cSrcweir */ 537cdf0e10cSrcweir register char *tp; 538cdf0e10cSrcweir 539cdf0e10cSrcweir if ((tp = strrchr(source, ']')) == NULL 540cdf0e10cSrcweir && (tp = strrchr(source, ':')) == NULL) 541cdf0e10cSrcweir return (FALSE); 542cdf0e10cSrcweir else { 543cdf0e10cSrcweir strncpy(result, source, tp - source + 1); 544cdf0e10cSrcweir result[tp - source + 1] = EOS; 545cdf0e10cSrcweir return (TRUE); 546cdf0e10cSrcweir } 547cdf0e10cSrcweir #endif 548cdf0e10cSrcweir #endif 549cdf0e10cSrcweir } 550cdf0e10cSrcweir 551cdf0e10cSrcweir #if HOST == SYS_VMS 552cdf0e10cSrcweir 553cdf0e10cSrcweir /* 554cdf0e10cSrcweir * EXP_DEV is set if a device was specified, EXP_DIR if a directory 555cdf0e10cSrcweir * is specified. (Both set indicate a file-logical, but EXP_DEV 556cdf0e10cSrcweir * would be set by itself if you are reading, say, SYS$INPUT:) 557cdf0e10cSrcweir */ 558cdf0e10cSrcweir #define DEVDIR (NAM$M_EXP_DEV | NAM$M_EXP_DIR) 559cdf0e10cSrcweir 560cdf0e10cSrcweir FILE_LOCAL int 561cdf0e10cSrcweir vmsparse(source, defstring, result) 562cdf0e10cSrcweir char *source; 563cdf0e10cSrcweir char *defstring; /* non-NULL -> default string. */ 564cdf0e10cSrcweir char *result; /* Size is at least NAM$C_MAXRSS + 1 */ 565cdf0e10cSrcweir /* 566cdf0e10cSrcweir * Parse the source string, applying the default (properly, using 567cdf0e10cSrcweir * the system parse routine), storing it in result. 568cdf0e10cSrcweir * TRUE if it parsed, FALSE on error. 569cdf0e10cSrcweir * 570cdf0e10cSrcweir * If defstring is NULL, there are no defaults and result gets 571cdf0e10cSrcweir * (just) the node::[directory] part of the string (possibly "") 572cdf0e10cSrcweir */ 573cdf0e10cSrcweir { 574cdf0e10cSrcweir struct FAB fab = cc$rms_fab; /* File access block */ 575cdf0e10cSrcweir struct NAM nam = cc$rms_nam; /* File name block */ 576cdf0e10cSrcweir char fullname[NAM$C_MAXRSS + 1]; 577cdf0e10cSrcweir register char *rp; /* Result pointer */ 578cdf0e10cSrcweir 579cdf0e10cSrcweir fab.fab$l_nam = &nam; /* fab -> nam */ 580cdf0e10cSrcweir fab.fab$l_fna = source; /* Source filename */ 581cdf0e10cSrcweir fab.fab$b_fns = strlen(source); /* Size of source */ 582cdf0e10cSrcweir fab.fab$l_dna = defstring; /* Default string */ 583cdf0e10cSrcweir if (defstring != NULLST) 584cdf0e10cSrcweir fab.fab$b_dns = strlen(defstring); /* Size of default */ 585cdf0e10cSrcweir nam.nam$l_esa = fullname; /* Expanded filename */ 586cdf0e10cSrcweir nam.nam$b_ess = NAM$C_MAXRSS; /* Expanded name size */ 587cdf0e10cSrcweir if (sys$parse(&fab) == RMS$_NORMAL) { /* Parse away */ 588cdf0e10cSrcweir fullname[nam.nam$b_esl] = EOS; /* Terminate string */ 589cdf0e10cSrcweir result[0] = EOS; /* Just in case */ 590cdf0e10cSrcweir rp = &result[0]; 591cdf0e10cSrcweir /* 592cdf0e10cSrcweir * Remove stuff added implicitly, accepting node names and 593cdf0e10cSrcweir * dev:[directory] strings (but not process-permanent files). 594cdf0e10cSrcweir */ 595cdf0e10cSrcweir if ((nam.nam$l_fnb & NAM$M_PPF) == 0) { 596cdf0e10cSrcweir if ((nam.nam$l_fnb & NAM$M_NODE) != 0) { 597cdf0e10cSrcweir strncpy(result, nam.nam$l_node, nam.nam$b_node); 598cdf0e10cSrcweir rp += nam.nam$b_node; 599cdf0e10cSrcweir *rp = EOS; 600cdf0e10cSrcweir } 601cdf0e10cSrcweir if ((nam.nam$l_fnb & DEVDIR) == DEVDIR) { 602cdf0e10cSrcweir strncpy(rp, nam.nam$l_dev, nam.nam$b_dev + nam.nam$b_dir); 603cdf0e10cSrcweir rp += nam.nam$b_dev + nam.nam$b_dir; 604cdf0e10cSrcweir *rp = EOS; 605cdf0e10cSrcweir } 606cdf0e10cSrcweir } 607cdf0e10cSrcweir if (defstring != NULLST) { 608cdf0e10cSrcweir strncpy(rp, nam.nam$l_name, nam.nam$b_name + nam.nam$b_type); 609cdf0e10cSrcweir rp += nam.nam$b_name + nam.nam$b_type; 610cdf0e10cSrcweir *rp = EOS; 611cdf0e10cSrcweir if ((nam.nam$l_fnb & NAM$M_EXP_VER) != 0) { 612cdf0e10cSrcweir strncpy(rp, nam.nam$l_ver, nam.nam$b_ver); 613cdf0e10cSrcweir rp[nam.nam$b_ver] = EOS; 614cdf0e10cSrcweir } 615cdf0e10cSrcweir } 616cdf0e10cSrcweir return (TRUE); 617cdf0e10cSrcweir } 618cdf0e10cSrcweir return (FALSE); 619cdf0e10cSrcweir } 620cdf0e10cSrcweir #endif 621cdf0e10cSrcweir 622