diff options
author | millaway <millaway> | 2002-08-14 00:46:59 +0000 |
---|---|---|
committer | millaway <millaway> | 2002-08-14 00:46:59 +0000 |
commit | 679a63011df105dffab6aea01716920aaa17ca08 (patch) | |
tree | 272b93a66e3c1d2e4ea4805f7093c37e7393d229 | |
parent | 06649eb9d87fc487eb43d53b4e36584af301e097 (diff) | |
download | flex-679a63011df105dffab6aea01716920aaa17ca08.tar.gz |
Start condition prefixes attempts to adjust to user preferences.
-rw-r--r-- | flex.texi | 28 | ||||
-rw-r--r-- | flexdef.h | 12 | ||||
-rw-r--r-- | main.c | 5 | ||||
-rw-r--r-- | misc.c | 102 |
4 files changed, 138 insertions, 9 deletions
@@ -1777,8 +1777,20 @@ assignments to @code{comment_caller} could instead be written Flex provides @code{YYSTATE} as an alias for @code{YY_START} (since that is what's used by AT&T @code{lex}). -Note that start conditions do not have their own name-space; %s's and %x's -declare names in the same fashion as #define's. +For historical reasons, start conditions do not have their own +name-space within the generated scanner. The start condition names are +unmodified in the generated scanner. However, they are prefixed +with @samp{yysc_} in the generated header, where @samp{yy} corresponds +to the appropriate prefix. Thus, @code{%x comment} produces +@code{#define comment n} in the scanner, and produces +@code{#define yysc_comment} +in the header. If you have already prefixed the start condition, +then flex attempts to respect your design by honoring the prefix. +Likewise, flex attempts to respect your capitalization convention. + +@xref{option-header}. @xref{option-prefix}. + + Finally, here's an example of how to match C-style quoted strings using exclusive start conditions, including expanded escape sequences (but @@ -2392,8 +2404,11 @@ and then exits. @anchor{option-header} @item --header=FILE instructs flex to write a C header to @file{FILE}. This file contains -function prototypes, extern variables, and macros used by the scanner. -It is meant to be included in other C files to avoid compiler warnings. +function prototypes, extern variables, and types used by the scanner. +Only the external API is exported by the header file. Many macros that +are usable from within scanner actions are not exported to the header +file. This is due to namespace problems and the goal of a clean +external API. The @samp{--header} option is not compatible with the @samp{--c++} option, since the C++ scanner provides its own header in @file{yyFlexLexer.h}. @@ -2727,13 +2742,14 @@ then the scanner is written to @file{stdout} but its @code{#line} directives (see the @samp{-l} option above) refer to the file @file{FILE}. +@anchor{option-prefix} @item -PPREFIX, --prefix=PREFIX changes the default @samp{yy} prefix used by @code{flex} for all globally-visible variable and function names to instead be @samp{PREFIX}. For example, @samp{--prefix=foo} changes the name of @code{yytext} to @code{footext}. It also changes the name of the default -output file from @file{lex.yy.c} to @file{lex.foo.c}. Here are all of -the names affected: +output file from @file{lex.yy.c} to @file{lex.foo.c}. Here is a partial +list of the names affected: @example @verbatim @@ -1078,4 +1078,16 @@ extern jmp_buf flex_main_jmp_buf; /* Removes all \n and \r chars from tail of str. returns str. */ extern char* chomp(char* str); +/* converts str to lowercase. returns str. */ +extern char * strlower (char *str); + +/* converts str to lowercase. returns str. */ +extern char * strupper (char *str); + +/* guess case preference for str */ +extern int case_preference (const char* str); + +/* creates a name-space safe copy of start cond name in buf. returns buf */ +extern char * fix_scname (char * buf, const char * name); + #endif /* not defined FLEXDEF_H */ @@ -568,9 +568,8 @@ int exit_status; /* Print the prefixed start conditions. */ for (i=1; i <= lastsc; i++) - fprintf(header_out, "#define %sSC_%s %d\n", - strcmp(prefix,"yy") ? prefix : "YY", - scname[i], i-1); + fprintf(header_out, "#define %s %d\n", + fix_scname(linebuf,scname[i]), i-1); /* Kill ALL flex-related macros. This is so the user * can #include more than one generated header file. */ @@ -933,3 +933,105 @@ char* chomp(str) *p-- = 0; return str; } + +/* Converts str to lowercase in place. returns str*/ +char * strlower (str) + char* str; +{ + char * s = str; + if (str) + for (s=str; *s; s++) + *s = tolower(*s); + return str; +} + +/* Converts str to uppercase in place. returns str*/ +char * strupper (str) + char* str; +{ + char * s; + if (str) + for (s=str; *s; s++) + *s = toupper(*s); + return str; +} + +/* return < 0 if prefers lowercase + * return > 0 if prefers uppercase + * return 0 if no preference or it looks like first-letter-capitalization + * Similar to strcmp(), the absolute value of the return value is larger + * the more characters are upper or lowercase. + */ +int case_preference (str) + const char* str; +{ + int nup=0, nlow=0, first_up=0; + const char* s; + if (!str) + return 0; + + /* find the first upper or lowercase letter */ + for (s=str; *s; s++){ + if (!isupper(*s) && !islower(*s)) + continue; + first_up = isupper(*s); + break; + } + + for (s=str; *s; s++){ + if (isupper(*s)) + nup++; + if (islower(*s)) + nlow++; + } + + return (first_up && nlow > nup) ? 0 : nup - nlow; +} + +/* Creates a name-space friendly start condition name, safe for + * use in the generated header. + * buf should be large enough to contain name and prefix. + * returns buf + */ +char * fix_scname (buf, name) + char * buf; + const char * name; +{ + char * pre; + int cn,cp; + + buf[0]= '\0'; + if (!name) + return buf; + + /* we do comparisons in lowercase */ + pre = copy_string(prefix); + strlower(pre); + strcpy(buf,name); + strlower(buf); + + /* If the user has already prefixed name, then we leave it alone. */ + if (strncmp(buf,pre,strlen(pre))==0 && strlen(name) > strlen(pre)){ + strcpy(buf,name); + free(pre); + return buf; + } + + /* Build the new name */ + sprintf(buf,"%ssc_%s", prefix, name); + + /* Decide whether the user prefers upper or lowercase or neither */ + cp = case_preference(prefix); + cn = case_preference(name); + + if (cn != 0) { + /* If it's mostly lowercase... */ + if (cn < 0 && (0 - cn) > strlen(name)/2) + strlower(buf); + else if (cn > 0 && cn > strlen(name)/2) + strupper(buf); + } + + free(pre); + return buf; +} |