summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormillaway <millaway>2002-08-14 00:46:59 +0000
committermillaway <millaway>2002-08-14 00:46:59 +0000
commit679a63011df105dffab6aea01716920aaa17ca08 (patch)
tree272b93a66e3c1d2e4ea4805f7093c37e7393d229
parent06649eb9d87fc487eb43d53b4e36584af301e097 (diff)
downloadflex-679a63011df105dffab6aea01716920aaa17ca08.tar.gz
Start condition prefixes attempts to adjust to user preferences.
-rw-r--r--flex.texi28
-rw-r--r--flexdef.h12
-rw-r--r--main.c5
-rw-r--r--misc.c102
4 files changed, 138 insertions, 9 deletions
diff --git a/flex.texi b/flex.texi
index b6dfea8..6224011 100644
--- a/flex.texi
+++ b/flex.texi
@@ -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
diff --git a/flexdef.h b/flexdef.h
index 0fb12e2..a7effb5 100644
--- a/flexdef.h
+++ b/flexdef.h
@@ -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 */
diff --git a/main.c b/main.c
index 4e47485..5edbd18 100644
--- a/main.c
+++ b/main.c
@@ -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. */
diff --git a/misc.c b/misc.c
index 5a86a23..2d5c9e7 100644
--- a/misc.c
+++ b/misc.c
@@ -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;
+}