STATIC TOKEN_T lexFileName( STRM_T s ) /************************************* * Now we need two ways of taking file names if the filename needs special * characters then use "filename" this will ignore all the different * characters except for the quote which can be specified as \t */ { char file[_MAX_PATH]; unsigned pos; assert( isfilec( s ) || s == DOUBLEQUOTE || ( (Glob.compat_nmake || Glob.compat_posix) && s == SPECIAL_TMP_DOL_C ) ); if( s == DOUBLEQUOTE ) { return( lexLongFilePathName( s, TOK_FILENAME ) ); } pos = 0; while( pos < _MAX_PATH && (isfilec( s ) || ( s == SPECIAL_TMP_DOL_C && (Glob.compat_nmake || Glob.compat_posix) ) ) ) { file[pos++] = s; s = PreGetCH(); } if( pos == _MAX_PATH ) { PrtMsgExit(( FTL | LOC | MAXIMUM_TOKEN_IS, _MAX_PATH - 1 )); // NOTREACHED } file[pos] = NULLCHAR; UnGetCH( s ); /* if it is a file, we have to check last position for a ':', and * trim it off if it's there */ if( pos > 1 && file[pos - 1] == COLON ) { file[pos - 1] = NULLCHAR; /* trim a trailing colon */ UnGetCH( COLON ); /* push back the colon */ --pos; } /* * try to do the trim twice because if file ends with a double colon * it means its a double colon explicit rule */ if( pos > 1 && file[pos - 1] == COLON ) { file[pos - 1] = NULLCHAR; /* trim a trailing colon */ UnGetCH( COLON ); /* push back the colon */ } CurAttr.u.ptr = StrDupSafe( file ); return( TOK_FILENAME ); }
int main( void ) /***************/ { int i; bool noneyet; /*printf( "extern UINT8 IsArray[] = {\n" );*/ printf( "/*STRM_MAGIC*/ 0,\n" ); printf( "/*STRM_END */ 0" ); /* note: no ",\n" !! */ for( i = 0; i <= 255; i++ ) { noneyet = true; if( isprint( i ) ) { printf( ",\n/* '%c' */ ", i ); } else { printf( ",\n/* 0x%02x */ ", i ); } if( isws( i ) ) { BAR( IS_WS ); } if( isprt( i ) ) { BAR( IS_PRINT ); } if( isalpha( i ) ) { BAR( IS_ALPHA ); } if( isextc( i ) ) { BAR( IS_EXTC ); } if( isdirc( i ) ) { BAR( IS_DIRC ); } if( isfilec( i ) ) { BAR( IS_FILEC ); } if( ismacc( i ) ) { BAR( IS_MACC ); } if( isbarf( i ) ) { BAR( IS_BARF ); } if( noneyet ) { printf( "0" ); } } /*printf("\n};\n");*/ printf( "\n" ); return( 0 ); }
TOKEN_T LexParser( STRM_T s ) /************************************ * returns: next token for parser * remarks: possibly defines a macro */ { static BOOLEAN atstart = TRUE; char *p; for( ;; ) { if( atstart ) { /* atstart == TRUE if either of these succeed */ if( isws( s ) ) { /* cmd line */ return( lexCmd() ); } if( ismacc( s ) && checkMacro( s ) ) { /* check if macro = body */ s = PreGetCH(); continue; } atstart = FALSE; UnGetCH( s ); /* put back our probe */ s = STRM_MAGIC; /* force macro expansion */ } switch( s ) { case STRM_END: atstart = TRUE; return( TOK_END ); case EOL: atstart = TRUE; return( TOK_EOL ); case STRM_TMP_LEX_START: case STRM_MAGIC: p = DeMacroDoubleQuote( FALSE ); /* expand to next white space */ if( *p == NULLCHAR ) { /* already at ws */ FreeSafe( p ); s = PreGetCH(); /* eat the ws */ while( isws( s ) ) { s = PreGetCH(); } if( s == EOL ) { atstart = TRUE; return( TOK_EOL ); } if( s == STRM_END ) { atstart = TRUE; return( TOK_END ); } UnGetCH( s ); p = DeMacroDoubleQuote( FALSE ); } UnGetCH( STRM_MAGIC ); /* mark spot we have to expand from nxt */ InsString( p, TRUE ); /* put expansion in stream */ break; case SPACE: /* fall through */ case TAB: break; case L_CURL_PAREN: /* could only be a sufsuf */ case DOT: UnGetCH( s ); return( lexDotName() ); /* could be a file... */ case SEMI: /* treat semi-colon as {nl}{ws} */ InsString( "\n ", FALSE ); break; /* try again */ case COLON: s = PreGetCH(); if( s == COLON ) { return( TOK_DCOLON ); } UnGetCH( s ); return( TOK_SCOLON ); default: if( isfilec( s ) || s == DOUBLEQUOTE || ( (Glob.compat_nmake || Glob.compat_posix) && s == SPECIAL_TMP_DOL_C ) ) { return( lexFileName( s ) ); } PrtMsg( WRN | LOC | UNKNOWN_TOKEN, s ); break; } s = PreGetCH(); /* fetch a character */ } }
TOKEN_T LexPath( STRM_T s ) /********************************* * returns: ({filec}*";")+ TOK_PATH * EOL EOL * STRM_END STRM_END */ { char path[_MAX_PATH]; char string_open; unsigned pos; VECSTR vec; /* we'll store file/path here */ for( ;; ) { /* get first valid character */ if( s == EOL || s == STRM_END ) { /* now we pass this to LexParser() so that it can reset */ return( LexParser( s ) ); } if( s == STRM_MAGIC ) { InsString( DeMacro( TOK_EOL ), TRUE ); } else if( !isfilec( s ) && s != PATH_SPLIT && s != ';' && s != '\"' && !isws( s ) ) { PrtMsg( ERR | LOC | EXPECTING_M, M_PATH ); } else if( !isws( s ) ) { break; } s = PreGetCH(); /* keep fetching characters */ } /* just so you know what we've got now */ assert( isfilec( s ) || s == PATH_SPLIT || s == ';' || s == '\"' ); vec = StartVec(); pos = 0; for( ;; ) { /* * Extract path from stream. If double quote is found, start string mode * and ignore all filename character specifiers and just copy all * characters. String mode ends with another double quote. Backslash can * be used to escape only double quotes, otherwise they are recognized * as path seperators. If we are not in string mode character validity * is checked against isfilec(). */ string_open = 0; while( pos < _MAX_PATH && s != EOL && s != STRM_END ) { if( s == BACKSLASH ) { s = PreGetCH(); if( s == DOUBLEQUOTE ) { path[pos++] = DOUBLEQUOTE; } else if( s == EOL || s == STRM_END ) { // Handle special case when backslash is placed at end of // line or file path[pos++] = BACKSLASH; } else { path[pos++] = BACKSLASH; // make sure we don't cross boundaries if( pos < _MAX_PATH ) { path[pos++] = s; } } } else { if( s == DOUBLEQUOTE ) { string_open = !string_open; } else { if( string_open ) { path[pos++] = s; } else if( isfilec( s ) ) { path[pos++] = s; } else { break; // not valid path character, break out. } } } s = PreGetCH(); } if( string_open ) { FreeSafe( FinishVec( vec ) ); PrtMsgExit(( FTL | LOC | ERROR_STRING_OPEN )); } if( pos == _MAX_PATH ) { FreeSafe( FinishVec( vec ) ); PrtMsgExit(( FTL | LOC | MAXIMUM_TOKEN_IS, _MAX_PATH - 1 )); // NOTREACHED } path[pos] = NULLCHAR; WriteVec( vec, path ); if( s != PATH_SPLIT && s != ';' ) { break; } pos = 0; path[pos++] = PATH_SPLIT; s = PreGetCH(); /* use Pre here to allow path;&(nl)path */ } UnGetCH( s ); CurAttr.u.ptr = FinishVec( vec ); return( TOK_PATH ); }
int expandfile(Text *t, uint q0, uint q1, Expand *e) { int i, n, nname, colon, eval; uint amin, amax; Rune *r, c; Window *w; Runestr rs; amax = q1; if(q1 == q0){ colon = -1; while(q1<t->file->b.nc && isfilec(c=textreadc(t, q1))){ if(c == ':'){ colon = q1; break; } q1++; } while(q0>0 && (isfilec(c=textreadc(t, q0-1)) || isaddrc(c) || isregexc(c))){ q0--; if(colon<0 && c==':') colon = q0; } /* * if it looks like it might begin file: , consume address chars after : * otherwise terminate expansion at : */ if(colon >= 0){ q1 = colon; if(colon<t->file->b.nc-1 && isaddrc(textreadc(t, colon+1))){ q1 = colon+1; while(q1<t->file->b.nc && isaddrc(textreadc(t, q1))) q1++; } } if(q1 > q0) if(colon >= 0){ /* stop at white space */ for(amax=colon+1; amax<t->file->b.nc; amax++) if((c=textreadc(t, amax))==' ' || c=='\t' || c=='\n') break; }else amax = t->file->b.nc; } amin = amax; e->q0 = q0; e->q1 = q1; n = q1-q0; if(n == 0) return FALSE; /* see if it's a file name */ r = runemalloc(n); bufread(&t->file->b, q0, r, n); /* first, does it have bad chars? */ nname = -1; for(i=0; i<n; i++){ c = r[i]; if(c==':' && nname<0){ if(q0+i+1<t->file->b.nc && (i==n-1 || isaddrc(textreadc(t, q0+i+1)))) amin = q0+i; else goto Isntfile; nname = i; } } if(nname == -1) nname = n; for(i=0; i<nname; i++) if(!isfilec(r[i])) goto Isntfile; /* * See if it's a file name in <>, and turn that into an include * file name if so. Should probably do it for "" too, but that's not * restrictive enough syntax and checking for a #include earlier on the * line would be silly. */ if(q0>0 && textreadc(t, q0-1)=='<' && q1<t->file->b.nc && textreadc(t, q1)=='>'){ rs = includename(t, r, nname); r = rs.r; nname = rs.nr; } else if(amin == q0) goto Isfile; else{ rs = dirname(t, r, nname); r = rs.r; nname = rs.nr; } e->bname = runetobyte(r, nname); /* if it's already a window name, it's a file */ w = lookfile(r, nname); if(w != nil) goto Isfile; /* if it's the name of a file, it's a file */ if(ismtpt(e->bname) || access(e->bname, 0) < 0){ free(e->bname); e->bname = nil; goto Isntfile; } Isfile: e->name = r; e->nname = nname; e->u.at = t; e->a0 = amin+1; eval = FALSE; address(TRUE, nil, range(-1,-1), range(0,0), t, e->a0, amax, tgetc, &eval, (uint*)&e->a1); return TRUE; Isntfile: free(r); return FALSE; }