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 <string.h> 31*cdf0e10cSrcweir #include "cppdef.h" 32*cdf0e10cSrcweir #include "cpp.h" 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir /*ER evaluate macros to pDefOut */ 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir /* 37*cdf0e10cSrcweir * skipnl() skips over input text to the end of the line. 38*cdf0e10cSrcweir * skipws() skips over "whitespace" (spaces or tabs), but 39*cdf0e10cSrcweir * not skip over the end of the line. It skips over 40*cdf0e10cSrcweir * TOK_SEP, however (though that shouldn't happen). 41*cdf0e10cSrcweir * scanid() reads the next token (C identifier) into token[]. 42*cdf0e10cSrcweir * The caller has already read the first character of 43*cdf0e10cSrcweir * the identifier. Unlike macroid(), the token is 44*cdf0e10cSrcweir * never expanded. 45*cdf0e10cSrcweir * macroid() reads the next token (C identifier) into token[]. 46*cdf0e10cSrcweir * If it is a #defined macro, it is expanded, and 47*cdf0e10cSrcweir * macroid() returns TRUE, otherwise, FALSE. 48*cdf0e10cSrcweir * catenate() Does the dirty work of token concatenation, TRUE if it did. 49*cdf0e10cSrcweir * scanstring() Reads a string from the input stream, calling 50*cdf0e10cSrcweir * a user-supplied function for each character. 51*cdf0e10cSrcweir * This function may be output() to write the 52*cdf0e10cSrcweir * string to the output file, or save() to save 53*cdf0e10cSrcweir * the string in the work buffer. 54*cdf0e10cSrcweir * scannumber() Reads a C numeric constant from the input stream, 55*cdf0e10cSrcweir * calling the user-supplied function for each 56*cdf0e10cSrcweir * character. (output() or save() as noted above.) 57*cdf0e10cSrcweir * save() Save one character in the work[] buffer. 58*cdf0e10cSrcweir * savestring() Saves a string in malloc() memory. 59*cdf0e10cSrcweir * getfile() Initialize a new FILEINFO structure, called when 60*cdf0e10cSrcweir * #include opens a new file, or a macro is to be 61*cdf0e10cSrcweir * expanded. 62*cdf0e10cSrcweir * getmem() Get a specified number of bytes from malloc memory. 63*cdf0e10cSrcweir * output() Write one character to stdout (calling PUTCHAR) -- 64*cdf0e10cSrcweir * implemented as a function so its address may be 65*cdf0e10cSrcweir * passed to scanstring() and scannumber(). 66*cdf0e10cSrcweir * lookid() Scans the next token (identifier) from the input 67*cdf0e10cSrcweir * stream. Looks for it in the #defined symbol table. 68*cdf0e10cSrcweir * Returns a pointer to the definition, if found, or NULL 69*cdf0e10cSrcweir * if not present. The identifier is stored in token[]. 70*cdf0e10cSrcweir * defnedel() Define enter/delete subroutine. Updates the 71*cdf0e10cSrcweir * symbol table. 72*cdf0e10cSrcweir * get() Read the next byte from the current input stream, 73*cdf0e10cSrcweir * handling end of (macro/file) input and embedded 74*cdf0e10cSrcweir * comments appropriately. Note that the global 75*cdf0e10cSrcweir * instring is -- essentially -- a parameter to get(). 76*cdf0e10cSrcweir * cget() Like get(), but skip over TOK_SEP. 77*cdf0e10cSrcweir * unget() Push last gotten character back on the input stream. 78*cdf0e10cSrcweir * cerror(), cwarn(), cfatal(), cierror(), ciwarn() 79*cdf0e10cSrcweir * These routines format an print messages to the user. 80*cdf0e10cSrcweir * cerror & cwarn take a format and a single string argument. 81*cdf0e10cSrcweir * cierror & ciwarn take a format and a single int (char) argument. 82*cdf0e10cSrcweir * cfatal takes a format and a single string argument. 83*cdf0e10cSrcweir */ 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir /* 86*cdf0e10cSrcweir * This table must be rewritten for a non-Ascii machine. 87*cdf0e10cSrcweir * 88*cdf0e10cSrcweir * Note that several "non-visible" characters have special meaning: 89*cdf0e10cSrcweir * Hex 1D DEF_MAGIC -- a flag to prevent #define recursion. 90*cdf0e10cSrcweir * Hex 1E TOK_SEP -- a delimiter for token concatenation 91*cdf0e10cSrcweir * Hex 1F COM_SEP -- a zero-width whitespace for comment concatenation 92*cdf0e10cSrcweir */ 93*cdf0e10cSrcweir #if TOK_SEP != 0x1E || COM_SEP != 0x1F || DEF_MAGIC != 0x1D 94*cdf0e10cSrcweir << error type table is not correct >> 95*cdf0e10cSrcweir #endif 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir #if OK_DOLLAR 98*cdf0e10cSrcweir #define DOL LET 99*cdf0e10cSrcweir #else 100*cdf0e10cSrcweir #define DOL 000 101*cdf0e10cSrcweir #endif 102*cdf0e10cSrcweir 103*cdf0e10cSrcweir #ifdef EBCDIC 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir char type[256] = { /* Character type codes Hex */ 106*cdf0e10cSrcweir END, 000, 000, 000, 000, SPA, 000, 000, /* 00 */ 107*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 08 */ 108*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 10 */ 109*cdf0e10cSrcweir 000, 000, 000, 000, 000, LET, 000, SPA, /* 18 */ 110*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 20 */ 111*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 28 */ 112*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 30 */ 113*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 38 */ 114*cdf0e10cSrcweir SPA, 000, 000, 000, 000, 000, 000, 000, /* 40 */ 115*cdf0e10cSrcweir 000, 000, 000, DOT, OP_LT,OP_LPA,OP_ADD, OP_OR, /* 48 .<(+| */ 116*cdf0e10cSrcweir OP_AND, 000, 000, 000, 000, 000, 000, 000, /* 50 & */ 117*cdf0e10cSrcweir 000, 000,OP_NOT, DOL,OP_MUL,OP_RPA, 000,OP_XOR, /* 58 !$*);^ */ 118*cdf0e10cSrcweir OP_SUB,OP_DIV, 000, 000, 000, 000, 000, 000, /* 60 -/ */ 119*cdf0e10cSrcweir 000, 000, 000, 000,OP_MOD, LET, OP_GT,OP_QUE, /* 68 ,%_>? */ 120*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 70 */ 121*cdf0e10cSrcweir 000, 000,OP_COL, 000, 000, QUO, OP_EQ, QUO, /* 78 `:#@'=" */ 122*cdf0e10cSrcweir 000, LET, LET, LET, LET, LET, LET, LET, /* 80 abcdefg */ 123*cdf0e10cSrcweir LET, LET, 000, 000, 000, 000, 000, 000, /* 88 hi */ 124*cdf0e10cSrcweir 000, LET, LET, LET, LET, LET, LET, LET, /* 90 jklmnop */ 125*cdf0e10cSrcweir LET, LET, 000, 000, 000, 000, 000, 000, /* 98 qr */ 126*cdf0e10cSrcweir 000,OP_NOT, LET, LET, LET, LET, LET, LET, /* A0 ~stuvwx */ 127*cdf0e10cSrcweir LET, LET, 000, 000, 000, 000, 000, 000, /* A8 yz [ */ 128*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* B0 */ 129*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* B8 ] */ 130*cdf0e10cSrcweir 000, LET, LET, LET, LET, LET, LET, LET, /* C0 {ABCDEFG */ 131*cdf0e10cSrcweir LET, LET, 000, 000, 000, 000, 000, 000, /* C8 HI */ 132*cdf0e10cSrcweir 000, LET, LET, LET, LET, LET, LET, LET, /* D0 }JKLMNOP */ 133*cdf0e10cSrcweir LET, LET, 000, 000, 000, 000, 000, 000, /* D8 QR */ 134*cdf0e10cSrcweir BSH, 000, LET, LET, LET, LET, LET, LET, /* E0 \ STUVWX */ 135*cdf0e10cSrcweir LET, LET, 000, 000, 000, 000, 000, 000, /* E8 YZ */ 136*cdf0e10cSrcweir DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, /* F0 01234567 */ 137*cdf0e10cSrcweir DIG, DIG, 000, 000, 000, 000, 000, 000, /* F8 89 */ 138*cdf0e10cSrcweir }; 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir #else 141*cdf0e10cSrcweir 142*cdf0e10cSrcweir char type[256] = { /* Character type codes Hex */ 143*cdf0e10cSrcweir END, 000, 000, 000, 000, 000, 000, 000, /* 00 */ 144*cdf0e10cSrcweir 000, SPA, 000, 000, 000, 000, 000, 000, /* 08 */ 145*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 10 */ 146*cdf0e10cSrcweir 000, 000, 000, 000, 000, LET, 000, SPA, /* 18 */ 147*cdf0e10cSrcweir SPA,OP_NOT, QUO, 000, DOL,OP_MOD,OP_AND, QUO, /* 20 !"#$%&' */ 148*cdf0e10cSrcweir OP_LPA,OP_RPA,OP_MUL,OP_ADD, 000,OP_SUB, DOT,OP_DIV, /* 28 ()*+,-./ */ 149*cdf0e10cSrcweir DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, /* 30 01234567 */ 150*cdf0e10cSrcweir DIG, DIG,OP_COL, 000, OP_LT, OP_EQ, OP_GT,OP_QUE, /* 38 89:;<=>? */ 151*cdf0e10cSrcweir 000, LET, LET, LET, LET, LET, LET, LET, /* 40 @ABCDEFG */ 152*cdf0e10cSrcweir LET, LET, LET, LET, LET, LET, LET, LET, /* 48 HIJKLMNO */ 153*cdf0e10cSrcweir LET, LET, LET, LET, LET, LET, LET, LET, /* 50 PQRSTUVW */ 154*cdf0e10cSrcweir LET, LET, LET, 000, BSH, 000,OP_XOR, LET, /* 58 XYZ[\]^_ */ 155*cdf0e10cSrcweir 000, LET, LET, LET, LET, LET, LET, LET, /* 60 `abcdefg */ 156*cdf0e10cSrcweir LET, LET, LET, LET, LET, LET, LET, LET, /* 68 hijklmno */ 157*cdf0e10cSrcweir LET, LET, LET, LET, LET, LET, LET, LET, /* 70 pqrstuvw */ 158*cdf0e10cSrcweir LET, LET, LET, 000, OP_OR, 000,OP_NOT, 000, /* 78 xyz{|}~ */ 159*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 160*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 161*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 162*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 163*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 164*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 165*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 166*cdf0e10cSrcweir 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 167*cdf0e10cSrcweir }; 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir #endif 170*cdf0e10cSrcweir 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir /* 173*cdf0e10cSrcweir * C P P S y m b o l T a b l e s 174*cdf0e10cSrcweir */ 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir /* 177*cdf0e10cSrcweir * SBSIZE defines the number of hash-table slots for the symbol table. 178*cdf0e10cSrcweir * It must be a power of 2. 179*cdf0e10cSrcweir */ 180*cdf0e10cSrcweir #ifndef SBSIZE 181*cdf0e10cSrcweir #define SBSIZE 64 182*cdf0e10cSrcweir #endif 183*cdf0e10cSrcweir #define SBMASK (SBSIZE - 1) 184*cdf0e10cSrcweir #if (SBSIZE ^ SBMASK) != ((SBSIZE * 2) - 1) 185*cdf0e10cSrcweir << error, SBSIZE must be a power of 2 >> 186*cdf0e10cSrcweir #endif 187*cdf0e10cSrcweir 188*cdf0e10cSrcweir 189*cdf0e10cSrcweir static DEFBUF *symtab[SBSIZE]; /* Symbol table queue headers */ 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir void InitCpp6() 192*cdf0e10cSrcweir { 193*cdf0e10cSrcweir int i; 194*cdf0e10cSrcweir for( i = 0; i < SBSIZE; i++ ) 195*cdf0e10cSrcweir symtab[ i ] = NULL; 196*cdf0e10cSrcweir } 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir void skipnl() 201*cdf0e10cSrcweir /* 202*cdf0e10cSrcweir * Skip to the end of the current input line. 203*cdf0e10cSrcweir */ 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir register int c; 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir do { /* Skip to newline */ 208*cdf0e10cSrcweir c = get(); 209*cdf0e10cSrcweir } while (c != '\n' && c != EOF_CHAR); 210*cdf0e10cSrcweir } 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir int 213*cdf0e10cSrcweir skipws() 214*cdf0e10cSrcweir /* 215*cdf0e10cSrcweir * Skip over whitespace 216*cdf0e10cSrcweir */ 217*cdf0e10cSrcweir { 218*cdf0e10cSrcweir register int c; 219*cdf0e10cSrcweir 220*cdf0e10cSrcweir do { /* Skip whitespace */ 221*cdf0e10cSrcweir c = get(); 222*cdf0e10cSrcweir #if COMMENT_INVISIBLE 223*cdf0e10cSrcweir } while (type[c] == SPA || c == COM_SEP); 224*cdf0e10cSrcweir #else 225*cdf0e10cSrcweir } while (type[c] == SPA); 226*cdf0e10cSrcweir #endif 227*cdf0e10cSrcweir return (c); 228*cdf0e10cSrcweir } 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir void scanid(int c) 231*cdf0e10cSrcweir /* 232*cdf0e10cSrcweir * Get the next token (an id) into the token buffer. 233*cdf0e10cSrcweir * Note: this code is duplicated in lookid(). 234*cdf0e10cSrcweir * Change one, change both. 235*cdf0e10cSrcweir */ 236*cdf0e10cSrcweir { 237*cdf0e10cSrcweir register char *bp; 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir if (c == DEF_MAGIC) /* Eat the magic token */ 240*cdf0e10cSrcweir c = get(); /* undefiner. */ 241*cdf0e10cSrcweir bp = token; 242*cdf0e10cSrcweir do { 243*cdf0e10cSrcweir if (bp < &token[IDMAX]) /* token dim is IDMAX+1 */ 244*cdf0e10cSrcweir *bp++ = (char)c; 245*cdf0e10cSrcweir c = get(); 246*cdf0e10cSrcweir } while (type[c] == LET || type[c] == DIG); 247*cdf0e10cSrcweir unget(); 248*cdf0e10cSrcweir *bp = EOS; 249*cdf0e10cSrcweir } 250*cdf0e10cSrcweir 251*cdf0e10cSrcweir int 252*cdf0e10cSrcweir macroid(int c) 253*cdf0e10cSrcweir /* 254*cdf0e10cSrcweir * If c is a letter, scan the id. if it's #defined, expand it and scan 255*cdf0e10cSrcweir * the next character and try again. 256*cdf0e10cSrcweir * 257*cdf0e10cSrcweir * Else, return the character. If type[c] is a LET, the token is in token. 258*cdf0e10cSrcweir */ 259*cdf0e10cSrcweir { 260*cdf0e10cSrcweir register DEFBUF *dp; 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir if (infile != NULL && infile->fp != NULL) 263*cdf0e10cSrcweir recursion = 0; 264*cdf0e10cSrcweir while (type[c] == LET && (dp = lookid(c)) != NULL) { 265*cdf0e10cSrcweir expand(dp); 266*cdf0e10cSrcweir c = get(); 267*cdf0e10cSrcweir } 268*cdf0e10cSrcweir return (c); 269*cdf0e10cSrcweir } 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir int 272*cdf0e10cSrcweir catenate() 273*cdf0e10cSrcweir /* 274*cdf0e10cSrcweir * A token was just read (via macroid). 275*cdf0e10cSrcweir * If the next character is TOK_SEP, concatenate the next token 276*cdf0e10cSrcweir * return TRUE -- which should recall macroid after refreshing 277*cdf0e10cSrcweir * macroid's argument. If it is not TOK_SEP, unget() the character 278*cdf0e10cSrcweir * and return FALSE. 279*cdf0e10cSrcweir */ 280*cdf0e10cSrcweir { 281*cdf0e10cSrcweir register int c; 282*cdf0e10cSrcweir register char *token1; 283*cdf0e10cSrcweir 284*cdf0e10cSrcweir #if OK_CONCAT 285*cdf0e10cSrcweir if (get() != TOK_SEP) { /* Token concatenation */ 286*cdf0e10cSrcweir unget(); 287*cdf0e10cSrcweir return (FALSE); 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir else { 290*cdf0e10cSrcweir token1 = savestring(token); /* Save first token */ 291*cdf0e10cSrcweir c = macroid(get()); /* Scan next token */ 292*cdf0e10cSrcweir switch(type[c]) { /* What was it? */ 293*cdf0e10cSrcweir case LET: /* An identifier, ... */ 294*cdf0e10cSrcweir if (strlen(token1) + strlen(token) >= NWORK) 295*cdf0e10cSrcweir cfatal("work buffer overflow doing %s #", token1); 296*cdf0e10cSrcweir sprintf(work, "%s%s", token1, token); 297*cdf0e10cSrcweir break; 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir case DIG: /* A digit string */ 300*cdf0e10cSrcweir strcpy(work, token1); 301*cdf0e10cSrcweir workp = work + strlen(work); 302*cdf0e10cSrcweir do { 303*cdf0e10cSrcweir save(c); 304*cdf0e10cSrcweir } while ((c = get()) != TOK_SEP); 305*cdf0e10cSrcweir /* 306*cdf0e10cSrcweir * The trailing TOK_SEP is no longer needed. 307*cdf0e10cSrcweir */ 308*cdf0e10cSrcweir save(EOS); 309*cdf0e10cSrcweir break; 310*cdf0e10cSrcweir 311*cdf0e10cSrcweir default: /* An error, ... */ 312*cdf0e10cSrcweir #if ! COMMENT_INVISIBLE 313*cdf0e10cSrcweir if (isprint(c)) 314*cdf0e10cSrcweir cierror("Strange character '%c' after #", c); 315*cdf0e10cSrcweir else 316*cdf0e10cSrcweir cierror("Strange character (%d.) after #", c); 317*cdf0e10cSrcweir #endif 318*cdf0e10cSrcweir strcpy(work, token1); 319*cdf0e10cSrcweir unget(); 320*cdf0e10cSrcweir break; 321*cdf0e10cSrcweir } 322*cdf0e10cSrcweir /* 323*cdf0e10cSrcweir * work has the concatenated token and token1 has 324*cdf0e10cSrcweir * the first token (no longer needed). Unget the 325*cdf0e10cSrcweir * new (concatenated) token after freeing token1. 326*cdf0e10cSrcweir * Finally, setup to read the new token. 327*cdf0e10cSrcweir */ 328*cdf0e10cSrcweir free(token1); /* Free up memory */ 329*cdf0e10cSrcweir ungetstring(work); /* Unget the new thing, */ 330*cdf0e10cSrcweir return (TRUE); 331*cdf0e10cSrcweir } 332*cdf0e10cSrcweir #else 333*cdf0e10cSrcweir return (FALSE); /* Not supported */ 334*cdf0e10cSrcweir #endif 335*cdf0e10cSrcweir } 336*cdf0e10cSrcweir 337*cdf0e10cSrcweir int 338*cdf0e10cSrcweir scanstring(int delim, 339*cdf0e10cSrcweir #ifndef _NO_PROTO 340*cdf0e10cSrcweir void (*outfun)( int ) /* BP */ /* Output function */ 341*cdf0e10cSrcweir #else 342*cdf0e10cSrcweir void (*outfun)() /* BP */ 343*cdf0e10cSrcweir #endif 344*cdf0e10cSrcweir ) 345*cdf0e10cSrcweir /* 346*cdf0e10cSrcweir * Scan off a string. Warning if terminated by newline or EOF. 347*cdf0e10cSrcweir * outfun() outputs the character -- to a buffer if in a macro. 348*cdf0e10cSrcweir * TRUE if ok, FALSE if error. 349*cdf0e10cSrcweir */ 350*cdf0e10cSrcweir { 351*cdf0e10cSrcweir register int c; 352*cdf0e10cSrcweir 353*cdf0e10cSrcweir instring = TRUE; /* Don't strip comments */ 354*cdf0e10cSrcweir (*outfun)(delim); 355*cdf0e10cSrcweir while ((c = get()) != delim 356*cdf0e10cSrcweir && c != '\n' 357*cdf0e10cSrcweir && c != EOF_CHAR) { 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir if (c != DEF_MAGIC) 360*cdf0e10cSrcweir (*outfun)(c); 361*cdf0e10cSrcweir if (c == '\\') 362*cdf0e10cSrcweir (*outfun)(get()); 363*cdf0e10cSrcweir } 364*cdf0e10cSrcweir instring = FALSE; 365*cdf0e10cSrcweir if (c == delim) { 366*cdf0e10cSrcweir (*outfun)(c); 367*cdf0e10cSrcweir return (TRUE); 368*cdf0e10cSrcweir } 369*cdf0e10cSrcweir else { 370*cdf0e10cSrcweir cerror("Unterminated string", NULLST); 371*cdf0e10cSrcweir unget(); 372*cdf0e10cSrcweir return (FALSE); 373*cdf0e10cSrcweir } 374*cdf0e10cSrcweir } 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir void scannumber(int c, 377*cdf0e10cSrcweir #ifndef _NO_PROTO 378*cdf0e10cSrcweir register void (*outfun)( int ) /* BP */ /* Output/store func */ 379*cdf0e10cSrcweir #else 380*cdf0e10cSrcweir register void (*outfun)() /* BP */ 381*cdf0e10cSrcweir #endif 382*cdf0e10cSrcweir ) 383*cdf0e10cSrcweir /* 384*cdf0e10cSrcweir * Process a number. We know that c is from 0 to 9 or dot. 385*cdf0e10cSrcweir * Algorithm from Dave Conroy's Decus C. 386*cdf0e10cSrcweir */ 387*cdf0e10cSrcweir { 388*cdf0e10cSrcweir register int radix; /* 8, 10, or 16 */ 389*cdf0e10cSrcweir int expseen; /* 'e' seen in floater */ 390*cdf0e10cSrcweir int signseen; /* '+' or '-' seen */ 391*cdf0e10cSrcweir int octal89; /* For bad octal test */ 392*cdf0e10cSrcweir int dotflag; /* TRUE if '.' was seen */ 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir expseen = FALSE; /* No exponent seen yet */ 395*cdf0e10cSrcweir signseen = TRUE; /* No +/- allowed yet */ 396*cdf0e10cSrcweir octal89 = FALSE; /* No bad octal yet */ 397*cdf0e10cSrcweir radix = 10; /* Assume decimal */ 398*cdf0e10cSrcweir if ((dotflag = (c == '.')) != FALSE) { /* . something? */ 399*cdf0e10cSrcweir (*outfun)('.'); /* Always out the dot */ 400*cdf0e10cSrcweir if (type[(c = get())] != DIG) { /* If not a float numb, */ 401*cdf0e10cSrcweir unget(); /* Rescan strange char */ 402*cdf0e10cSrcweir return; /* All done for now */ 403*cdf0e10cSrcweir } 404*cdf0e10cSrcweir } /* End of float test */ 405*cdf0e10cSrcweir else if (c == '0') { /* Octal or hex? */ 406*cdf0e10cSrcweir (*outfun)(c); /* Stuff initial zero */ 407*cdf0e10cSrcweir radix = 8; /* Assume it's octal */ 408*cdf0e10cSrcweir c = get(); /* Look for an 'x' */ 409*cdf0e10cSrcweir if (c == 'x' || c == 'X') { /* Did we get one? */ 410*cdf0e10cSrcweir radix = 16; /* Remember new radix */ 411*cdf0e10cSrcweir (*outfun)(c); /* Stuff the 'x' */ 412*cdf0e10cSrcweir c = get(); /* Get next character */ 413*cdf0e10cSrcweir } 414*cdf0e10cSrcweir } 415*cdf0e10cSrcweir for (;;) { /* Process curr. char. */ 416*cdf0e10cSrcweir /* 417*cdf0e10cSrcweir * Note that this algorithm accepts "012e4" and "03.4" 418*cdf0e10cSrcweir * as legitimate floating-point numbers. 419*cdf0e10cSrcweir */ 420*cdf0e10cSrcweir if (radix != 16 && (c == 'e' || c == 'E')) { 421*cdf0e10cSrcweir if (expseen) /* Already saw 'E'? */ 422*cdf0e10cSrcweir break; /* Exit loop, bad nbr. */ 423*cdf0e10cSrcweir expseen = TRUE; /* Set exponent seen */ 424*cdf0e10cSrcweir signseen = FALSE; /* We can read '+' now */ 425*cdf0e10cSrcweir radix = 10; /* Decimal exponent */ 426*cdf0e10cSrcweir } 427*cdf0e10cSrcweir else if (radix != 16 && c == '.') { 428*cdf0e10cSrcweir if (dotflag) /* Saw dot already? */ 429*cdf0e10cSrcweir break; /* Exit loop, two dots */ 430*cdf0e10cSrcweir dotflag = TRUE; /* Remember the dot */ 431*cdf0e10cSrcweir radix = 10; /* Decimal fraction */ 432*cdf0e10cSrcweir } 433*cdf0e10cSrcweir else if (c == '+' || c == '-') { /* 1.0e+10 */ 434*cdf0e10cSrcweir if (signseen) /* Sign in wrong place? */ 435*cdf0e10cSrcweir break; /* Exit loop, not nbr. */ 436*cdf0e10cSrcweir /* signseen = TRUE; */ /* Remember we saw it */ 437*cdf0e10cSrcweir } 438*cdf0e10cSrcweir else { /* Check the digit */ 439*cdf0e10cSrcweir switch (c) { 440*cdf0e10cSrcweir case '8': case '9': /* Sometimes wrong */ 441*cdf0e10cSrcweir octal89 = TRUE; /* Do check later */ 442*cdf0e10cSrcweir case '0': case '1': case '2': case '3': 443*cdf0e10cSrcweir case '4': case '5': case '6': case '7': 444*cdf0e10cSrcweir break; /* Always ok */ 445*cdf0e10cSrcweir 446*cdf0e10cSrcweir case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 447*cdf0e10cSrcweir case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 448*cdf0e10cSrcweir if (radix == 16) /* Alpha's are ok only */ 449*cdf0e10cSrcweir break; /* if reading hex. */ 450*cdf0e10cSrcweir default: /* At number end */ 451*cdf0e10cSrcweir goto done; /* Break from for loop */ 452*cdf0e10cSrcweir } /* End of switch */ 453*cdf0e10cSrcweir } /* End general case */ 454*cdf0e10cSrcweir (*outfun)(c); /* Accept the character */ 455*cdf0e10cSrcweir signseen = TRUE; /* Don't read sign now */ 456*cdf0e10cSrcweir c = get(); /* Read another char */ 457*cdf0e10cSrcweir } /* End of scan loop */ 458*cdf0e10cSrcweir /* 459*cdf0e10cSrcweir * When we break out of the scan loop, c contains the first 460*cdf0e10cSrcweir * character (maybe) not in the number. If the number is an 461*cdf0e10cSrcweir * integer, allow a trailing 'L' for long and/or a trailing 'U' 462*cdf0e10cSrcweir * for unsigned. If not those, push the trailing character back 463*cdf0e10cSrcweir * on the input stream. Floating point numbers accept a trailing 464*cdf0e10cSrcweir * 'L' for "long double". 465*cdf0e10cSrcweir */ 466*cdf0e10cSrcweir done: if (dotflag || expseen) { /* Floating point? */ 467*cdf0e10cSrcweir if (c == 'l' || c == 'L') { 468*cdf0e10cSrcweir (*outfun)(c); 469*cdf0e10cSrcweir c = get(); /* Ungotten later */ 470*cdf0e10cSrcweir } 471*cdf0e10cSrcweir } 472*cdf0e10cSrcweir else { /* Else it's an integer */ 473*cdf0e10cSrcweir /* 474*cdf0e10cSrcweir * We know that dotflag and expseen are both zero, now: 475*cdf0e10cSrcweir * dotflag signals "saw 'L'", and 476*cdf0e10cSrcweir * expseen signals "saw 'U'". 477*cdf0e10cSrcweir */ 478*cdf0e10cSrcweir for (;;) { 479*cdf0e10cSrcweir switch (c) { 480*cdf0e10cSrcweir case 'l': 481*cdf0e10cSrcweir case 'L': 482*cdf0e10cSrcweir if (dotflag) 483*cdf0e10cSrcweir goto nomore; 484*cdf0e10cSrcweir dotflag = TRUE; 485*cdf0e10cSrcweir break; 486*cdf0e10cSrcweir 487*cdf0e10cSrcweir case 'u': 488*cdf0e10cSrcweir case 'U': 489*cdf0e10cSrcweir if (expseen) 490*cdf0e10cSrcweir goto nomore; 491*cdf0e10cSrcweir expseen = TRUE; 492*cdf0e10cSrcweir break; 493*cdf0e10cSrcweir 494*cdf0e10cSrcweir default: 495*cdf0e10cSrcweir goto nomore; 496*cdf0e10cSrcweir } 497*cdf0e10cSrcweir (*outfun)(c); /* Got 'L' or 'U'. */ 498*cdf0e10cSrcweir c = get(); /* Look at next, too. */ 499*cdf0e10cSrcweir } 500*cdf0e10cSrcweir } 501*cdf0e10cSrcweir nomore: unget(); /* Not part of a number */ 502*cdf0e10cSrcweir if (octal89 && radix == 8) 503*cdf0e10cSrcweir cwarn("Illegal digit in octal number", NULLST); 504*cdf0e10cSrcweir } 505*cdf0e10cSrcweir 506*cdf0e10cSrcweir void save(int c) 507*cdf0e10cSrcweir { 508*cdf0e10cSrcweir if (workp >= &work[NWORK]) { 509*cdf0e10cSrcweir work[NWORK-1] = '\0'; 510*cdf0e10cSrcweir cfatal("Work buffer overflow: %s", work); 511*cdf0e10cSrcweir } 512*cdf0e10cSrcweir else *workp++ = (char)c; 513*cdf0e10cSrcweir } 514*cdf0e10cSrcweir 515*cdf0e10cSrcweir char * 516*cdf0e10cSrcweir savestring(char* text) 517*cdf0e10cSrcweir /* 518*cdf0e10cSrcweir * Store a string into free memory. 519*cdf0e10cSrcweir */ 520*cdf0e10cSrcweir { 521*cdf0e10cSrcweir register char *result; 522*cdf0e10cSrcweir 523*cdf0e10cSrcweir result = getmem(strlen(text) + 1); 524*cdf0e10cSrcweir strcpy(result, text); 525*cdf0e10cSrcweir return (result); 526*cdf0e10cSrcweir } 527*cdf0e10cSrcweir 528*cdf0e10cSrcweir FILEINFO * 529*cdf0e10cSrcweir getfile(int bufsize, char* name) 530*cdf0e10cSrcweir /* 531*cdf0e10cSrcweir * Common FILEINFO buffer initialization for a new file or macro. 532*cdf0e10cSrcweir */ 533*cdf0e10cSrcweir { 534*cdf0e10cSrcweir register FILEINFO *file; 535*cdf0e10cSrcweir register int size; 536*cdf0e10cSrcweir 537*cdf0e10cSrcweir size = strlen(name); /* File/macro name */ 538*cdf0e10cSrcweir file = (FILEINFO *) getmem(sizeof (FILEINFO) + bufsize + size); 539*cdf0e10cSrcweir file->parent = infile; /* Chain files together */ 540*cdf0e10cSrcweir file->fp = NULL; /* No file yet */ 541*cdf0e10cSrcweir file->filename = savestring(name); /* Save file/macro name */ 542*cdf0e10cSrcweir file->progname = NULL; /* No #line seen yet */ 543*cdf0e10cSrcweir file->unrecur = 0; /* No macro fixup */ 544*cdf0e10cSrcweir file->bptr = file->buffer; /* Initialize line ptr */ 545*cdf0e10cSrcweir file->buffer[0] = EOS; /* Force first read */ 546*cdf0e10cSrcweir file->line = 0; /* (Not used just yet) */ 547*cdf0e10cSrcweir if (infile != NULL) /* If #include file */ 548*cdf0e10cSrcweir infile->line = line; /* Save current line */ 549*cdf0e10cSrcweir infile = file; /* New current file */ 550*cdf0e10cSrcweir line = 1; /* Note first line */ 551*cdf0e10cSrcweir return (file); /* All done. */ 552*cdf0e10cSrcweir } 553*cdf0e10cSrcweir 554*cdf0e10cSrcweir char * 555*cdf0e10cSrcweir getmem(int size) 556*cdf0e10cSrcweir /* 557*cdf0e10cSrcweir * Get a block of free memory. 558*cdf0e10cSrcweir */ 559*cdf0e10cSrcweir { 560*cdf0e10cSrcweir register char *result; 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir if ((result = malloc((unsigned) size)) == NULL) 563*cdf0e10cSrcweir cfatal("Out of memory", NULLST); 564*cdf0e10cSrcweir return (result); 565*cdf0e10cSrcweir } 566*cdf0e10cSrcweir 567*cdf0e10cSrcweir 568*cdf0e10cSrcweir DEFBUF * 569*cdf0e10cSrcweir lookid(int c) 570*cdf0e10cSrcweir /* 571*cdf0e10cSrcweir * Look for the next token in the symbol table. Returns token in "token". 572*cdf0e10cSrcweir * If found, returns the table pointer; Else returns NULL. 573*cdf0e10cSrcweir */ 574*cdf0e10cSrcweir { 575*cdf0e10cSrcweir register int nhash; 576*cdf0e10cSrcweir register DEFBUF *dp; 577*cdf0e10cSrcweir register char *np; 578*cdf0e10cSrcweir int temp = 0; 579*cdf0e10cSrcweir int isrecurse; /* For #define foo foo */ 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir np = token; 582*cdf0e10cSrcweir nhash = 0; 583*cdf0e10cSrcweir if (0 != (isrecurse = (c == DEF_MAGIC))) /* If recursive macro */ 584*cdf0e10cSrcweir c = get(); /* hack, skip DEF_MAGIC */ 585*cdf0e10cSrcweir do { 586*cdf0e10cSrcweir if (np < &token[IDMAX]) { /* token dim is IDMAX+1 */ 587*cdf0e10cSrcweir *np++ = (char)c; /* Store token byte */ 588*cdf0e10cSrcweir nhash += c; /* Update hash value */ 589*cdf0e10cSrcweir } 590*cdf0e10cSrcweir c = get(); /* And get another byte */ 591*cdf0e10cSrcweir } while (type[c] == LET || type[c] == DIG); 592*cdf0e10cSrcweir unget(); /* Rescan terminator */ 593*cdf0e10cSrcweir *np = EOS; /* Terminate token */ 594*cdf0e10cSrcweir if (isrecurse) /* Recursive definition */ 595*cdf0e10cSrcweir return (NULL); /* undefined just now */ 596*cdf0e10cSrcweir nhash += (np - token); /* Fix hash value */ 597*cdf0e10cSrcweir dp = symtab[nhash & SBMASK]; /* Starting bucket */ 598*cdf0e10cSrcweir while (dp != (DEFBUF *) NULL) { /* Search symbol table */ 599*cdf0e10cSrcweir if (dp->hash == nhash /* Fast precheck */ 600*cdf0e10cSrcweir && (temp = strcmp(dp->name, token)) >= 0) 601*cdf0e10cSrcweir break; 602*cdf0e10cSrcweir dp = dp->link; /* Nope, try next one */ 603*cdf0e10cSrcweir } 604*cdf0e10cSrcweir return ((temp == 0) ? dp : NULL); 605*cdf0e10cSrcweir } 606*cdf0e10cSrcweir 607*cdf0e10cSrcweir DEFBUF * 608*cdf0e10cSrcweir defendel(char* name, int delete) 609*cdf0e10cSrcweir /* 610*cdf0e10cSrcweir * Enter this name in the lookup table (delete = FALSE) 611*cdf0e10cSrcweir * or delete this name (delete = TRUE). 612*cdf0e10cSrcweir * Returns a pointer to the define block (delete = FALSE) 613*cdf0e10cSrcweir * Returns NULL if the symbol wasn't defined (delete = TRUE). 614*cdf0e10cSrcweir */ 615*cdf0e10cSrcweir { 616*cdf0e10cSrcweir register DEFBUF *dp; 617*cdf0e10cSrcweir register DEFBUF **prevp; 618*cdf0e10cSrcweir register char *np; 619*cdf0e10cSrcweir int nhash; 620*cdf0e10cSrcweir int temp; 621*cdf0e10cSrcweir int size; 622*cdf0e10cSrcweir 623*cdf0e10cSrcweir for (nhash = 0, np = name; *np != EOS;) 624*cdf0e10cSrcweir nhash += *np++; 625*cdf0e10cSrcweir size = (np - name); 626*cdf0e10cSrcweir nhash += size; 627*cdf0e10cSrcweir prevp = &symtab[nhash & SBMASK]; 628*cdf0e10cSrcweir while ((dp = *prevp) != (DEFBUF *) NULL) { 629*cdf0e10cSrcweir if (dp->hash == nhash 630*cdf0e10cSrcweir && (temp = strcmp(dp->name, name)) >= 0) { 631*cdf0e10cSrcweir if (temp > 0) 632*cdf0e10cSrcweir dp = NULL; /* Not found */ 633*cdf0e10cSrcweir else { 634*cdf0e10cSrcweir *prevp = dp->link; /* Found, unlink and */ 635*cdf0e10cSrcweir if (dp->repl != NULL) /* Free the replacement */ 636*cdf0e10cSrcweir free(dp->repl); /* if any, and then */ 637*cdf0e10cSrcweir free((char *) dp); /* Free the symbol */ 638*cdf0e10cSrcweir } 639*cdf0e10cSrcweir break; 640*cdf0e10cSrcweir } 641*cdf0e10cSrcweir prevp = &dp->link; 642*cdf0e10cSrcweir } 643*cdf0e10cSrcweir if (!delete) { 644*cdf0e10cSrcweir dp = (DEFBUF *) getmem(sizeof (DEFBUF) + size); 645*cdf0e10cSrcweir dp->link = *prevp; 646*cdf0e10cSrcweir *prevp = dp; 647*cdf0e10cSrcweir dp->hash = nhash; 648*cdf0e10cSrcweir dp->repl = NULL; 649*cdf0e10cSrcweir dp->nargs = 0; 650*cdf0e10cSrcweir strcpy(dp->name, name); 651*cdf0e10cSrcweir } 652*cdf0e10cSrcweir return (dp); 653*cdf0e10cSrcweir } 654*cdf0e10cSrcweir 655*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 656*cdf0e10cSrcweir 657*cdf0e10cSrcweir void dumpdef(char *why) 658*cdf0e10cSrcweir { 659*cdf0e10cSrcweir register DEFBUF *dp; 660*cdf0e10cSrcweir register DEFBUF **syp; 661*cdf0e10cSrcweir FILE *pRememberOut = NULL; 662*cdf0e10cSrcweir 663*cdf0e10cSrcweir if ( bDumpDefs ) /*ER */ 664*cdf0e10cSrcweir { 665*cdf0e10cSrcweir pRememberOut = pCppOut; 666*cdf0e10cSrcweir pCppOut = pDefOut; 667*cdf0e10cSrcweir } 668*cdf0e10cSrcweir fprintf( pCppOut, "CPP symbol table dump %s\n", why); 669*cdf0e10cSrcweir for (syp = symtab; syp < &symtab[SBSIZE]; syp++) { 670*cdf0e10cSrcweir if ((dp = *syp) != (DEFBUF *) NULL) { 671*cdf0e10cSrcweir fprintf( pCppOut, "symtab[%d]\n", (syp - symtab)); 672*cdf0e10cSrcweir do { 673*cdf0e10cSrcweir dumpadef((char *) NULL, dp); 674*cdf0e10cSrcweir } while ((dp = dp->link) != (DEFBUF *) NULL); 675*cdf0e10cSrcweir } 676*cdf0e10cSrcweir } 677*cdf0e10cSrcweir if ( bDumpDefs ) 678*cdf0e10cSrcweir { 679*cdf0e10cSrcweir fprintf( pCppOut, "\n"); 680*cdf0e10cSrcweir pCppOut = pRememberOut; 681*cdf0e10cSrcweir } 682*cdf0e10cSrcweir } 683*cdf0e10cSrcweir 684*cdf0e10cSrcweir void dumpadef(char *why, register DEFBUF *dp) 685*cdf0e10cSrcweir { 686*cdf0e10cSrcweir register char *cp; 687*cdf0e10cSrcweir register int c; 688*cdf0e10cSrcweir FILE *pRememberOut = NULL; 689*cdf0e10cSrcweir 690*cdf0e10cSrcweir /*ER dump #define's to pDefOut */ 691*cdf0e10cSrcweir if ( bDumpDefs ) 692*cdf0e10cSrcweir { 693*cdf0e10cSrcweir pRememberOut = pCppOut; 694*cdf0e10cSrcweir pCppOut = pDefOut; 695*cdf0e10cSrcweir } 696*cdf0e10cSrcweir fprintf( pCppOut, " \"%s\" [%d]", dp->name, dp->nargs); 697*cdf0e10cSrcweir if (why != NULL) 698*cdf0e10cSrcweir fprintf( pCppOut, " (%s)", why); 699*cdf0e10cSrcweir if (dp->repl != NULL) { 700*cdf0e10cSrcweir fprintf( pCppOut, " => "); 701*cdf0e10cSrcweir for (cp = dp->repl; (c = *cp++ & 0xFF) != EOS;) { 702*cdf0e10cSrcweir #ifdef SOLAR 703*cdf0e10cSrcweir if (c == DEL) { 704*cdf0e10cSrcweir c = *cp++ & 0xFF; 705*cdf0e10cSrcweir if( c == EOS ) break; 706*cdf0e10cSrcweir fprintf( pCppOut, "<%%%d>", c - MAC_PARM); 707*cdf0e10cSrcweir } 708*cdf0e10cSrcweir #else 709*cdf0e10cSrcweir if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC)) 710*cdf0e10cSrcweir fprintf( pCppOut, "<%%%d>", c - MAC_PARM); 711*cdf0e10cSrcweir #endif 712*cdf0e10cSrcweir else if (isprint(c) || c == '\n' || c == '\t') 713*cdf0e10cSrcweir PUTCHAR(c); 714*cdf0e10cSrcweir else if (c < ' ') 715*cdf0e10cSrcweir fprintf( pCppOut, "<^%c>", c + '@'); 716*cdf0e10cSrcweir else 717*cdf0e10cSrcweir fprintf( pCppOut, "<\\0%o>", c); 718*cdf0e10cSrcweir } 719*cdf0e10cSrcweir /*ER evaluate macros to pDefOut */ 720*cdf0e10cSrcweir #ifdef EVALDEFS 721*cdf0e10cSrcweir if ( bDumpDefs && !bIsInEval && dp->nargs <= 0 ) 722*cdf0e10cSrcweir { 723*cdf0e10cSrcweir FILEINFO *infileSave = infile; 724*cdf0e10cSrcweir char *tokenSave = savestring( token ); 725*cdf0e10cSrcweir char *workSave = savestring( work ); 726*cdf0e10cSrcweir int lineSave = line; 727*cdf0e10cSrcweir int wronglineSave = wrongline; 728*cdf0e10cSrcweir int recursionSave = recursion; 729*cdf0e10cSrcweir FILEINFO *file; 730*cdf0e10cSrcweir EVALTYPE valEval; 731*cdf0e10cSrcweir 732*cdf0e10cSrcweir bIsInEval = 1; 733*cdf0e10cSrcweir infile = NULL; /* start from scrap */ 734*cdf0e10cSrcweir line = 0; 735*cdf0e10cSrcweir wrongline = 0; 736*cdf0e10cSrcweir *token = EOS; 737*cdf0e10cSrcweir *work = EOS; 738*cdf0e10cSrcweir recursion = 0; 739*cdf0e10cSrcweir file = getfile( strlen( dp->repl ), dp->name ); 740*cdf0e10cSrcweir strcpy( file->buffer, dp->repl ); 741*cdf0e10cSrcweir fprintf( pCppOut, " ===> "); 742*cdf0e10cSrcweir nEvalOff = 0; 743*cdf0e10cSrcweir cppmain(); /* get() frees also *file */ 744*cdf0e10cSrcweir valEval = 0; 745*cdf0e10cSrcweir if ( 0 == evaluate( EvalBuf, &valEval ) ) 746*cdf0e10cSrcweir { 747*cdf0e10cSrcweir #ifdef EVALFLOATS 748*cdf0e10cSrcweir if ( valEval != (EVALTYPE)((long)valEval ) ) 749*cdf0e10cSrcweir fprintf( pCppOut, " ==eval=> %f", valEval ); 750*cdf0e10cSrcweir else 751*cdf0e10cSrcweir #endif 752*cdf0e10cSrcweir fprintf( pCppOut, " ==eval=> %ld", (long)valEval ); 753*cdf0e10cSrcweir } 754*cdf0e10cSrcweir recursion = recursionSave; 755*cdf0e10cSrcweir wrongline = wronglineSave; 756*cdf0e10cSrcweir line = lineSave; 757*cdf0e10cSrcweir strcpy( work, workSave ); 758*cdf0e10cSrcweir free( workSave ); 759*cdf0e10cSrcweir strcpy( token, tokenSave ); 760*cdf0e10cSrcweir free( tokenSave ); 761*cdf0e10cSrcweir infile = infileSave; 762*cdf0e10cSrcweir bIsInEval = 0; 763*cdf0e10cSrcweir } 764*cdf0e10cSrcweir #endif 765*cdf0e10cSrcweir } 766*cdf0e10cSrcweir else { 767*cdf0e10cSrcweir fprintf( pCppOut, ", no replacement."); 768*cdf0e10cSrcweir } 769*cdf0e10cSrcweir PUTCHAR('\n'); 770*cdf0e10cSrcweir if ( bDumpDefs ) 771*cdf0e10cSrcweir pCppOut = pRememberOut; 772*cdf0e10cSrcweir } 773*cdf0e10cSrcweir #endif 774*cdf0e10cSrcweir 775*cdf0e10cSrcweir /* 776*cdf0e10cSrcweir * G E T 777*cdf0e10cSrcweir */ 778*cdf0e10cSrcweir 779*cdf0e10cSrcweir int 780*cdf0e10cSrcweir get() 781*cdf0e10cSrcweir /* 782*cdf0e10cSrcweir * Return the next character from a macro or the current file. 783*cdf0e10cSrcweir * Handle end of file from #include files. 784*cdf0e10cSrcweir */ 785*cdf0e10cSrcweir { 786*cdf0e10cSrcweir register int c; 787*cdf0e10cSrcweir register FILEINFO *file; 788*cdf0e10cSrcweir register int popped; /* Recursion fixup */ 789*cdf0e10cSrcweir 790*cdf0e10cSrcweir popped = 0; 791*cdf0e10cSrcweir get_from_file: 792*cdf0e10cSrcweir if ((file = infile) == NULL) 793*cdf0e10cSrcweir return (EOF_CHAR); 794*cdf0e10cSrcweir newline: 795*cdf0e10cSrcweir #if 0 796*cdf0e10cSrcweir fprintf( pCppOut, "get(%s), recursion %d, line %d, bptr = %d, buffer \"%s\"\n", 797*cdf0e10cSrcweir file->filename, recursion, line, 798*cdf0e10cSrcweir file->bptr - file->buffer, file->buffer); 799*cdf0e10cSrcweir #endif 800*cdf0e10cSrcweir /* 801*cdf0e10cSrcweir * Read a character from the current input line or macro. 802*cdf0e10cSrcweir * At EOS, either finish the current macro (freeing temp. 803*cdf0e10cSrcweir * storage) or read another line from the current input file. 804*cdf0e10cSrcweir * At EOF, exit the current file (#include) or, at EOF from 805*cdf0e10cSrcweir * the cpp input file, return EOF_CHAR to finish processing. 806*cdf0e10cSrcweir */ 807*cdf0e10cSrcweir if ((c = *file->bptr++ & 0xFF) == EOS) { 808*cdf0e10cSrcweir /* 809*cdf0e10cSrcweir * Nothing in current line or macro. Get next line (if 810*cdf0e10cSrcweir * input from a file), or do end of file/macro processing. 811*cdf0e10cSrcweir * In the latter case, jump back to restart from the top. 812*cdf0e10cSrcweir */ 813*cdf0e10cSrcweir if (file->fp == NULL) { /* NULL if macro */ 814*cdf0e10cSrcweir popped++; 815*cdf0e10cSrcweir recursion -= file->unrecur; 816*cdf0e10cSrcweir if (recursion < 0) 817*cdf0e10cSrcweir recursion = 0; 818*cdf0e10cSrcweir infile = file->parent; /* Unwind file chain */ 819*cdf0e10cSrcweir } 820*cdf0e10cSrcweir else { /* Else get from a file */ 821*cdf0e10cSrcweir if ((file->bptr = fgets(file->buffer, NBUFF, file->fp)) 822*cdf0e10cSrcweir != NULL) { 823*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 824*cdf0e10cSrcweir if (debug > 1) { /* Dump it to stdout */ 825*cdf0e10cSrcweir fprintf( pCppOut, "\n#line %d (%s), %s", 826*cdf0e10cSrcweir line, file->filename, file->buffer); 827*cdf0e10cSrcweir } 828*cdf0e10cSrcweir #endif 829*cdf0e10cSrcweir goto newline; /* process the line */ 830*cdf0e10cSrcweir } 831*cdf0e10cSrcweir else { 832*cdf0e10cSrcweir if( file->fp != stdin ) 833*cdf0e10cSrcweir fclose(file->fp); /* Close finished file */ 834*cdf0e10cSrcweir if ((infile = file->parent) != NULL) { 835*cdf0e10cSrcweir /* 836*cdf0e10cSrcweir * There is an "ungotten" newline in the current 837*cdf0e10cSrcweir * infile buffer (set there by doinclude() in 838*cdf0e10cSrcweir * cpp1.c). Thus, we know that the mainline code 839*cdf0e10cSrcweir * is skipping over blank lines and will do a 840*cdf0e10cSrcweir * #line at its convenience. 841*cdf0e10cSrcweir */ 842*cdf0e10cSrcweir wrongline = TRUE; /* Need a #line now */ 843*cdf0e10cSrcweir } 844*cdf0e10cSrcweir } 845*cdf0e10cSrcweir } 846*cdf0e10cSrcweir /* 847*cdf0e10cSrcweir * Free up space used by the (finished) file or macro and 848*cdf0e10cSrcweir * restart input from the parent file/macro, if any. 849*cdf0e10cSrcweir */ 850*cdf0e10cSrcweir free(file->filename); /* Free name and */ 851*cdf0e10cSrcweir if (file->progname != NULL) /* if a #line was seen, */ 852*cdf0e10cSrcweir free(file->progname); /* free it, too. */ 853*cdf0e10cSrcweir free((char *) file); /* Free file space */ 854*cdf0e10cSrcweir if (infile == NULL) /* If at end of file */ 855*cdf0e10cSrcweir return (EOF_CHAR); /* Return end of file */ 856*cdf0e10cSrcweir line = infile->line; /* Reset line number */ 857*cdf0e10cSrcweir goto get_from_file; /* Get from the top. */ 858*cdf0e10cSrcweir } 859*cdf0e10cSrcweir /* 860*cdf0e10cSrcweir * Common processing for the new character. 861*cdf0e10cSrcweir */ 862*cdf0e10cSrcweir if (c == DEF_MAGIC && file->fp != NULL) /* Don't allow delete */ 863*cdf0e10cSrcweir goto newline; /* from a file */ 864*cdf0e10cSrcweir if (file->parent != NULL) { /* Macro or #include */ 865*cdf0e10cSrcweir if (popped != 0) 866*cdf0e10cSrcweir file->parent->unrecur += popped; 867*cdf0e10cSrcweir else { 868*cdf0e10cSrcweir recursion -= file->parent->unrecur; 869*cdf0e10cSrcweir if (recursion < 0) 870*cdf0e10cSrcweir recursion = 0; 871*cdf0e10cSrcweir file->parent->unrecur = 0; 872*cdf0e10cSrcweir } 873*cdf0e10cSrcweir } 874*cdf0e10cSrcweir #if (HOST == SYS_UNIX) 875*cdf0e10cSrcweir /*ER*/ if (c == '\r') 876*cdf0e10cSrcweir /*ER*/ return get(); /* DOS fuck */ 877*cdf0e10cSrcweir #endif 878*cdf0e10cSrcweir if (c == '\n') /* Maintain current */ 879*cdf0e10cSrcweir ++line; /* line counter */ 880*cdf0e10cSrcweir if (instring) /* Strings just return */ 881*cdf0e10cSrcweir return (c); /* the character. */ 882*cdf0e10cSrcweir else if (c == '/') { /* Comment? */ 883*cdf0e10cSrcweir instring = TRUE; /* So get() won't loop */ 884*cdf0e10cSrcweir /*MM c++ comments */ 885*cdf0e10cSrcweir /*MM*/ c = get(); 886*cdf0e10cSrcweir /*MM*/ if ((c != '*') && (c != '/')) { /* Next byte '*'? */ 887*cdf0e10cSrcweir instring = FALSE; /* Nope, no comment */ 888*cdf0e10cSrcweir unget(); /* Push the char. back */ 889*cdf0e10cSrcweir return ('/'); /* Return the slash */ 890*cdf0e10cSrcweir } 891*cdf0e10cSrcweir if (keepcomments) { /* If writing comments */ 892*cdf0e10cSrcweir PUTCHAR('/'); /* Write out the */ 893*cdf0e10cSrcweir /* initializer */ 894*cdf0e10cSrcweir /*MM*/ if( '*' == c ) 895*cdf0e10cSrcweir PUTCHAR('*'); 896*cdf0e10cSrcweir /*MM*/ else 897*cdf0e10cSrcweir /*MM*/ PUTCHAR('/'); 898*cdf0e10cSrcweir 899*cdf0e10cSrcweir } 900*cdf0e10cSrcweir /*MM*/ if( '*' == c ){ 901*cdf0e10cSrcweir for (;;) { /* Eat a comment */ 902*cdf0e10cSrcweir c = get(); 903*cdf0e10cSrcweir test: if (keepcomments && c != EOF_CHAR) 904*cdf0e10cSrcweir cput(c); 905*cdf0e10cSrcweir switch (c) { 906*cdf0e10cSrcweir case EOF_CHAR: 907*cdf0e10cSrcweir cerror("EOF in comment", NULLST); 908*cdf0e10cSrcweir return (EOF_CHAR); 909*cdf0e10cSrcweir 910*cdf0e10cSrcweir case '/': 911*cdf0e10cSrcweir if ((c = get()) != '*') /* Don't let comments */ 912*cdf0e10cSrcweir goto test; /* Nest. */ 913*cdf0e10cSrcweir #ifdef STRICT_COMMENTS 914*cdf0e10cSrcweir cwarn("Nested comments", NULLST); 915*cdf0e10cSrcweir #endif 916*cdf0e10cSrcweir /* Fall into * stuff */ 917*cdf0e10cSrcweir case '*': 918*cdf0e10cSrcweir if ((c = get()) != '/') /* If comment doesn't */ 919*cdf0e10cSrcweir goto test; /* end, look at next */ 920*cdf0e10cSrcweir instring = FALSE; /* End of comment, */ 921*cdf0e10cSrcweir if (keepcomments) { /* Put out the comment */ 922*cdf0e10cSrcweir cput(c); /* terminator, too */ 923*cdf0e10cSrcweir } 924*cdf0e10cSrcweir /* 925*cdf0e10cSrcweir * A comment is syntactically "whitespace" -- 926*cdf0e10cSrcweir * however, there are certain strange sequences 927*cdf0e10cSrcweir * such as 928*cdf0e10cSrcweir * #define foo(x) (something) 929*cdf0e10cSrcweir * foo|* comment *|(123) 930*cdf0e10cSrcweir * these are '/' ^ ^ 931*cdf0e10cSrcweir * where just returning space (or COM_SEP) will cause 932*cdf0e10cSrcweir * problems. This can be "fixed" by overwriting the 933*cdf0e10cSrcweir * '/' in the input line buffer with ' ' (or COM_SEP) 934*cdf0e10cSrcweir * but that may mess up an error message. 935*cdf0e10cSrcweir * So, we peek ahead -- if the next character is 936*cdf0e10cSrcweir * "whitespace" we just get another character, if not, 937*cdf0e10cSrcweir * we modify the buffer. All in the name of purity. 938*cdf0e10cSrcweir */ 939*cdf0e10cSrcweir if (*file->bptr == '\n' 940*cdf0e10cSrcweir || type[*file->bptr & 0xFF] == SPA) 941*cdf0e10cSrcweir goto newline; 942*cdf0e10cSrcweir #if COMMENT_INVISIBLE 943*cdf0e10cSrcweir /* 944*cdf0e10cSrcweir * Return magic (old-fashioned) syntactic space. 945*cdf0e10cSrcweir */ 946*cdf0e10cSrcweir return ((file->bptr[-1] = COM_SEP)); 947*cdf0e10cSrcweir #else 948*cdf0e10cSrcweir return ((file->bptr[-1] = ' ')); 949*cdf0e10cSrcweir #endif 950*cdf0e10cSrcweir 951*cdf0e10cSrcweir case '\n': /* we'll need a #line */ 952*cdf0e10cSrcweir if (!keepcomments) 953*cdf0e10cSrcweir wrongline = TRUE; /* later... */ 954*cdf0e10cSrcweir default: /* Anything else is */ 955*cdf0e10cSrcweir break; /* Just a character */ 956*cdf0e10cSrcweir } /* End switch */ 957*cdf0e10cSrcweir } /* End comment loop */ 958*cdf0e10cSrcweir } 959*cdf0e10cSrcweir else{ /* c++ comment */ 960*cdf0e10cSrcweir /*MM c++ comment*/ 961*cdf0e10cSrcweir for (;;) { /* Eat a comment */ 962*cdf0e10cSrcweir c = get(); 963*cdf0e10cSrcweir if (keepcomments && c != EOF_CHAR) 964*cdf0e10cSrcweir cput(c); 965*cdf0e10cSrcweir if( EOF_CHAR == c ) 966*cdf0e10cSrcweir return (EOF_CHAR); 967*cdf0e10cSrcweir else if( '\n' == c ){ 968*cdf0e10cSrcweir instring = FALSE; /* End of comment, */ 969*cdf0e10cSrcweir return( c ); 970*cdf0e10cSrcweir } 971*cdf0e10cSrcweir } 972*cdf0e10cSrcweir } 973*cdf0e10cSrcweir } /* End if in comment */ 974*cdf0e10cSrcweir else if (!inmacro && c == '\\') { /* If backslash, peek */ 975*cdf0e10cSrcweir if ((c = get()) == '\n') { /* for a <nl>. If so, */ 976*cdf0e10cSrcweir wrongline = TRUE; 977*cdf0e10cSrcweir goto newline; 978*cdf0e10cSrcweir } 979*cdf0e10cSrcweir else { /* Backslash anything */ 980*cdf0e10cSrcweir unget(); /* Get it later */ 981*cdf0e10cSrcweir return ('\\'); /* Return the backslash */ 982*cdf0e10cSrcweir } 983*cdf0e10cSrcweir } 984*cdf0e10cSrcweir else if (c == '\f' || c == VT) /* Form Feed, Vertical */ 985*cdf0e10cSrcweir c = ' '; /* Tab are whitespace */ 986*cdf0e10cSrcweir else if (c == 0xef) /* eat up UTF-8 BOM */ 987*cdf0e10cSrcweir { 988*cdf0e10cSrcweir if((c = get()) == 0xbb) 989*cdf0e10cSrcweir { 990*cdf0e10cSrcweir if((c = get()) == 0xbf) 991*cdf0e10cSrcweir { 992*cdf0e10cSrcweir c = get(); 993*cdf0e10cSrcweir return c; 994*cdf0e10cSrcweir } 995*cdf0e10cSrcweir else 996*cdf0e10cSrcweir { 997*cdf0e10cSrcweir unget(); 998*cdf0e10cSrcweir unget(); 999*cdf0e10cSrcweir return 0xef; 1000*cdf0e10cSrcweir } 1001*cdf0e10cSrcweir } 1002*cdf0e10cSrcweir else 1003*cdf0e10cSrcweir { 1004*cdf0e10cSrcweir unget(); 1005*cdf0e10cSrcweir return 0xef; 1006*cdf0e10cSrcweir } 1007*cdf0e10cSrcweir } 1008*cdf0e10cSrcweir return (c); /* Just return the char */ 1009*cdf0e10cSrcweir } 1010*cdf0e10cSrcweir 1011*cdf0e10cSrcweir void unget() 1012*cdf0e10cSrcweir /* 1013*cdf0e10cSrcweir * Backup the pointer to reread the last character. Fatal error 1014*cdf0e10cSrcweir * (code bug) if we backup too far. unget() may be called, 1015*cdf0e10cSrcweir * without problems, at end of file. Only one character may 1016*cdf0e10cSrcweir * be ungotten. If you need to unget more, call ungetstring(). 1017*cdf0e10cSrcweir */ 1018*cdf0e10cSrcweir { 1019*cdf0e10cSrcweir register FILEINFO *file; 1020*cdf0e10cSrcweir 1021*cdf0e10cSrcweir if ((file = infile) == NULL) 1022*cdf0e10cSrcweir return; /* Unget after EOF */ 1023*cdf0e10cSrcweir if (--file->bptr < file->buffer) 1024*cdf0e10cSrcweir cfatal("Too much pushback", NULLST); 1025*cdf0e10cSrcweir if (*file->bptr == '\n') /* Ungetting a newline? */ 1026*cdf0e10cSrcweir --line; /* Unget the line number, too */ 1027*cdf0e10cSrcweir } 1028*cdf0e10cSrcweir 1029*cdf0e10cSrcweir void ungetstring(char* text) 1030*cdf0e10cSrcweir /* 1031*cdf0e10cSrcweir * Push a string back on the input stream. This is done by treating 1032*cdf0e10cSrcweir * the text as if it were a macro. 1033*cdf0e10cSrcweir */ 1034*cdf0e10cSrcweir { 1035*cdf0e10cSrcweir register FILEINFO *file; 1036*cdf0e10cSrcweir #ifndef ZTC /* BP */ 1037*cdf0e10cSrcweir extern FILEINFO *getfile(); 1038*cdf0e10cSrcweir #endif 1039*cdf0e10cSrcweir file = getfile(strlen(text) + 1, ""); 1040*cdf0e10cSrcweir strcpy(file->buffer, text); 1041*cdf0e10cSrcweir } 1042*cdf0e10cSrcweir 1043*cdf0e10cSrcweir int 1044*cdf0e10cSrcweir cget() 1045*cdf0e10cSrcweir /* 1046*cdf0e10cSrcweir * Get one character, absorb "funny space" after comments or 1047*cdf0e10cSrcweir * token concatenation 1048*cdf0e10cSrcweir */ 1049*cdf0e10cSrcweir { 1050*cdf0e10cSrcweir register int c; 1051*cdf0e10cSrcweir 1052*cdf0e10cSrcweir do { 1053*cdf0e10cSrcweir c = get(); 1054*cdf0e10cSrcweir #if COMMENT_INVISIBLE 1055*cdf0e10cSrcweir } while (c == TOK_SEP || c == COM_SEP); 1056*cdf0e10cSrcweir #else 1057*cdf0e10cSrcweir } while (c == TOK_SEP); 1058*cdf0e10cSrcweir #endif 1059*cdf0e10cSrcweir return (c); 1060*cdf0e10cSrcweir } 1061*cdf0e10cSrcweir 1062*cdf0e10cSrcweir /* 1063*cdf0e10cSrcweir * Error messages and other hacks. The first byte of severity 1064*cdf0e10cSrcweir * is 'S' for string arguments and 'I' for int arguments. This 1065*cdf0e10cSrcweir * is needed for portability with machines that have int's that 1066*cdf0e10cSrcweir * are shorter than char *'s. 1067*cdf0e10cSrcweir */ 1068*cdf0e10cSrcweir 1069*cdf0e10cSrcweir static void domsg(char* severity, char* format, void* arg) 1070*cdf0e10cSrcweir /* 1071*cdf0e10cSrcweir * Print filenames, macro names, and line numbers for error messages. 1072*cdf0e10cSrcweir */ 1073*cdf0e10cSrcweir { 1074*cdf0e10cSrcweir register char *tp; 1075*cdf0e10cSrcweir register FILEINFO *file; 1076*cdf0e10cSrcweir 1077*cdf0e10cSrcweir fprintf(stderr, "%sline %d, %s: ", MSG_PREFIX, line, &severity[1]); 1078*cdf0e10cSrcweir if (*severity == 'S') 1079*cdf0e10cSrcweir fprintf(stderr, format, (char *)arg); 1080*cdf0e10cSrcweir else 1081*cdf0e10cSrcweir fprintf(stderr, format, *((int *)arg) ); 1082*cdf0e10cSrcweir putc('\n', stderr); 1083*cdf0e10cSrcweir if ((file = infile) == NULL) 1084*cdf0e10cSrcweir return; /* At end of file */ 1085*cdf0e10cSrcweir if (file->fp != NULL) { 1086*cdf0e10cSrcweir tp = file->buffer; /* Print current file */ 1087*cdf0e10cSrcweir fprintf(stderr, "%s", tp); /* name, making sure */ 1088*cdf0e10cSrcweir if (tp[strlen(tp) - 1] != '\n') /* there's a newline */ 1089*cdf0e10cSrcweir putc('\n', stderr); 1090*cdf0e10cSrcweir } 1091*cdf0e10cSrcweir while ((file = file->parent) != NULL) { /* Print #includes, too */ 1092*cdf0e10cSrcweir if (file->fp == NULL) 1093*cdf0e10cSrcweir fprintf(stderr, "from macro %s\n", file->filename); 1094*cdf0e10cSrcweir else { 1095*cdf0e10cSrcweir tp = file->buffer; 1096*cdf0e10cSrcweir fprintf(stderr, "from file %s, line %d:\n%s", 1097*cdf0e10cSrcweir (file->progname != NULL) 1098*cdf0e10cSrcweir ? file->progname : file->filename, 1099*cdf0e10cSrcweir file->line, tp); 1100*cdf0e10cSrcweir if (tp[strlen(tp) - 1] != '\n') 1101*cdf0e10cSrcweir putc('\n', stderr); 1102*cdf0e10cSrcweir } 1103*cdf0e10cSrcweir } 1104*cdf0e10cSrcweir } 1105*cdf0e10cSrcweir 1106*cdf0e10cSrcweir void cerror(char* format, char* sarg) 1107*cdf0e10cSrcweir /* 1108*cdf0e10cSrcweir * Print a normal error message, string argument. 1109*cdf0e10cSrcweir */ 1110*cdf0e10cSrcweir { 1111*cdf0e10cSrcweir domsg("SError", format, sarg); 1112*cdf0e10cSrcweir errors++; 1113*cdf0e10cSrcweir } 1114*cdf0e10cSrcweir 1115*cdf0e10cSrcweir void cierror(char* format, int narg) 1116*cdf0e10cSrcweir /* 1117*cdf0e10cSrcweir * Print a normal error message, numeric argument. 1118*cdf0e10cSrcweir */ 1119*cdf0e10cSrcweir { 1120*cdf0e10cSrcweir domsg("IError", format, &narg); 1121*cdf0e10cSrcweir errors++; 1122*cdf0e10cSrcweir } 1123*cdf0e10cSrcweir 1124*cdf0e10cSrcweir void cfatal(char* format, char* sarg) 1125*cdf0e10cSrcweir /* 1126*cdf0e10cSrcweir * A real disaster 1127*cdf0e10cSrcweir */ 1128*cdf0e10cSrcweir { 1129*cdf0e10cSrcweir domsg("SFatal error", format, sarg); 1130*cdf0e10cSrcweir exit(IO_ERROR); 1131*cdf0e10cSrcweir } 1132*cdf0e10cSrcweir 1133*cdf0e10cSrcweir void cwarn(char* format, char* sarg) 1134*cdf0e10cSrcweir /* 1135*cdf0e10cSrcweir * A non-fatal error, string argument. 1136*cdf0e10cSrcweir */ 1137*cdf0e10cSrcweir { 1138*cdf0e10cSrcweir domsg("SWarning", format, sarg); 1139*cdf0e10cSrcweir } 1140*cdf0e10cSrcweir 1141*cdf0e10cSrcweir void ciwarn(char* format, int narg) 1142*cdf0e10cSrcweir /* 1143*cdf0e10cSrcweir * A non-fatal error, numeric argument. 1144*cdf0e10cSrcweir */ 1145*cdf0e10cSrcweir { 1146*cdf0e10cSrcweir domsg("IWarning", format, &narg); 1147*cdf0e10cSrcweir } 1148*cdf0e10cSrcweir 1149