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