107 lines · 3.0 KB · C
RawDownload
/* * Sample code showing how to use ucpp as an integrated lexer. * This file is public domain. */ /* * This is an example of how to use ucpp as a preprocessor and lexer * into another project. The steps are those described in ucpp README * file. To use this code, compile the ucpp source files with * STAND_ALONE not defined, and link them with this code. The resulting * binary will take a C source file as standard input, preprocess it, * and output each non-whitespace token on stdout, with its numerical * value (defined as an enum in cpp.h) and its contents. This code * defines no system include path. * * This code supposes that the ucpp files are compiled with PRAGMA_TOKENIZE * enabled (see the tune.h file). */ #include <stdio.h>#include <stdlib.h>#include <string.h>#include "mem.h"#include "cpp.h" int main(int argc, char *argv[]){	int i, r;	struct lexer_state ls; 	/* step 1 */	init_cpp(); 	/* step 2 */	no_special_macros = 0;	emit_defines = emit_assertions = 0; 	/* step 3 -- with assertions */	init_tables(1); 	/* step 4 -- no default include path */	init_include_path(0); 	/* step 5 -- no need to reset the two emit_* variables set in 2 */	emit_dependencies = 0; 	/* step 6 -- we work with stdin, this is not a real filename */	set_init_filename("[stdin]", 0); 	/* step 7 -- we make sure that assertions are on, and pragma are	   handled */	init_lexer_state(&ls);	init_lexer_mode(&ls);	ls.flags |= HANDLE_ASSERTIONS | HANDLE_PRAGMA | LINE_NUM; 	/* step 8 -- input is from stdin */	ls.input = stdin; 	/* step 9 -- we do not have any macro to define, but we add any	   argument as an include path */	for (i = 1; i < argc; i ++) add_incpath(argv[i]); 	/* step 10 -- we are a lexer and we want CONTEXT tokens */	enter_file(&ls, ls.flags); 	/* read tokens until end-of-input is reached -- errors (non-zero	   return values different from CPPERR_EOF) are ignored */	while ((r = lex(&ls)) < CPPERR_EOF) {		if (r) {			/* error condition -- no token was retrieved */			continue;		}		/* we print each token: its numerical value, and its		   string content; if this is a PRAGMA token, the		   string content is in fact a compressed token list,		   that we uncompress and print. */		if (ls.ctok->type == PRAGMA) {			unsigned char *c = (unsigned char *)(ls.ctok->name); 			printf("line %ld: <#pragma>\n", ls.line);			for (; *c; c ++) {				int t = *c; 				if (STRING_TOKEN(t)) {					printf("  <%2d>  ", t);					for (c ++; *c != PRAGMA_TOKEN_END;						c ++) putchar(*c);					putchar('\n');				} else {					printf("  <%2d>  `%s'\n", t,						operators_name[t]);				}			}		} else if (ls.ctok->type == CONTEXT) {			printf("new context: file '%s', line %ld\n",				ls.ctok->name, ls.ctok->line);		} else if (ls.ctok->type == NEWLINE) {			printf("[newline]\n");		} else {			printf("line %ld: <%2d>  `%s'\n", ls.ctok->line,				ls.ctok->type,				STRING_TOKEN(ls.ctok->type) ? ls.ctok->name				: operators_name[ls.ctok->type]);		}	}	return 0;}