lkml.org 
[lkml]   [1999]   [Jun]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: 2.x.x mkdep incorrectly handles serial.c (and probably others)
Hi Michael.

>> Changing CONFIG_SERIAL_SHARE_IRQ with no other changes does
>> *not* recompile serial.c but it should.

> Good bug report. Ok, I believe I see the problem. Here is the
> structure of drivers/char/serial.c:

> #if 0
> #define CONFIG_SERIAL_MANY_PORTS
> ...
> #endif

> ... uses of CONFIG_SERIAL_MANY_PORTS ...

> mkdep.c sees the definition of CONFIG_SERIAL_MANY_PORTS and says
> "oh this is not an autoconfig variable; serial.c explicitly
> defines it". This is why your patch to serial.c avoids the
> problem. It's really a bug in mkdep.c: it doesn't understand
> the effects of #if lines.

Can I offer the enclosed patch to deal with this problem?

Basically, the patch does three things:

1. Inserts a slight optimisation into mkdep's state machine whereby
the checks for space/tab are combined, and in the process also
checks for other whitespace characters at that point.

2. Modifies mkdep's state machine to include partial #if-#endif
parsing to deal with the above problem. Basically, the mods
result in it treating the contents of a "#if 0"-#endif block
as a comment, and not acting on any definitions therein.

3. Documenting the resulting state machine - this is the 100-odd
line comment at the beginning of the patch. Discard it if you
prefer, that doesn't worry me.

Note that the patch is against the 2.2.10 source tree, but as mkdep.c
carries a timestamp prior to the release of 2.2.0, it should patch
unchanged against 2.2.0 and all subsequent kernel source trees.

Also note that some of the lines in the patch are just reformatting
the existing code. I found that reformatting necessary to work out
how the state machine worked, and included them as a result.

Best wishes from Riley.

+----------------------------------------------------------------------+
| There is something frustrating about the quality and speed of Linux |
| development, ie., the quality is too high and the speed is too high, |
| in other words, I can implement this XXXX feature, but I bet someone |
| else has already done so and is just about to release their patch. |
+----------------------------------------------------------------------+
* ftp://ftp.MemAlpha.cx/pub/rhw/Linux
* http://www.MemAlpha.cx/kernel.versions.html--- linux-2.2.10/scripts/mkdep.c~ Fri Jan 8 19:10:11 1999
+++ linux-2.2.10/scripts/mkdep.c Tue Jun 15 15:17:15 1999
@@ -8,6 +8,104 @@
* I make simple dependency lines for #include <*.h> and #include "*.h".
* I also find instances of CONFIG_FOO and generate dependencies
* like include/config/foo.h.
+ *
+ * There is also sufficient handling of #if-#endif blocks to enable
+ * this program to ignore the contents of '#if 0'-'#endif' blocks
+ * with any level of internal #if-#endif nesting.
+ *
+ **********************************************************************
+ *
+ * The state machine used by this program starts in state 0 with the
+ * variable ifdepth set to 0. It uses the term "Space" to refer to the
+ * case where the isspace() function returns true, and is as follows:
+ *
+ * 0. Read a character, and change state as follows:
+ *
+ * "'" '"' '/' 'C' '_' '#' Other
+ * --- --- --- --- --- --- -----
+ * 1 2 3 4 6 8 0
+ *
+ * 1. Read in a string bounded by single quotes and handle it, then
+ * change to state 0.
+ *
+ * 2. Read in a string bounded by double quotes and handle it, then
+ * change to state 0.
+ *
+ * 3. Read in the following character. If this is a '*' (producing
+ * the sequence "/*"), read in more characters until the sequence
+ * "*/" is found, and handle them. Either way, change to state 0.
+ *
+ * 4. If the variable ifdepth has a value greater than zero, change
+ * to state 0, otherwise change to state 5.
+ *
+ * 5. Determine if this is the start of a sequence reading "CONFIG_"
+ * and, if so, handle it. Either way, change to state 0.
+ *
+ * 6. If the variable ifdepth has a value greater than zero, change
+ * to state 0, otherwise change to state 7.
+ *
+ * 7. Determine if this is the start of a sequence reading "__SMP__"
+ * and, if so, handle it. Either way, change to state 0.
+ *
+ * 8. Read a character, and change state as follows:
+ *
+ * 'd' 'u' 'e' 'i' Space Other
+ * --- --- --- --- ----- -----
+ * 9 11 13 15 8 0
+ *
+ * 9. If the variable ifdepth has a value greater than zero, change
+ * to state 0, otherwise change to state 10.
+ *
+ * 10. Determine if the characters so far are the start of a sequence
+ * reading "#define" and, if so, handle it. Either way, change to
+ * state 0.
+ *
+ * 11. If the variable ifdepth has a value greater than zero, change
+ * to state 0, otherwise change to state 10.
+ *
+ * 12. Determine if the characters so far are the start of a sequence
+ * reading "#undef" and, if so, handle it. Either way, change to
+ * state 0.
+ *
+ * 13. If the variable ifdepth has a value greater than zero, change
+ * to state 14, otherwise change to state 0.
+ *
+ * 14. Determine if the characters so far are the start of a sequence
+ * reading "#endif" and, if so, decrement the variable ifdepth.
+ * Either way, change to state 0.
+ *
+ * 15. Read a character, and change state as follows:
+ *
+ * 'f' 'n' Other
+ * --- --- -----
+ * 16 19 0
+ *
+ * 16. If the variable ifdepth has a value greater than zero, increment
+ * it and change to state 0, otherwise change to state 17.
+ *
+ * 17. Read a character. If it is a Space, change to state 18, otherwise
+ * change to state 0.
+ *
+ * 18. Read a character. If it is a '0' (thus producing the sequence
+ * "#if 0"), increment the variable ifdepth. Either way, change to
+ * state 0.
+ *
+ * 19. If the variable ifdepth has a value greater than zero, change
+ * to state 0, otherwise change to state 20.
+ *
+ * 20. Determine if the characters so far are the start of a sequence
+ * reading "#include" and, if so, change to state 21, else change
+ * to state 0.
+ *
+ * 21. Read a character, and change state as follows:
+ *
+ * '<' '"' Space Other
+ * --- --- ----- -----
+ * 22 23 21 0
+ *
+ * 22. Handle a '#include <header.h>' line, then change to state 0.
+ *
+ * 23. Handle a '#include "header.h"' line, then change to state 0.
*/

#include <ctype.h>
@@ -221,6 +319,9 @@
#define CASE(c,label) if (current == c) goto label
#define NOTCASE(c,label) if (current != c) goto label

+#define SPACE(label) if (isspace(current)) goto label
+#define NOTSPACE(label) if (!isspace(current)) goto label
+
/*
* Yet another state machine speedup.
*/
@@ -254,6 +355,7 @@
const char * next = map;
const char * map_dot;
unsigned long __buf = 0;
+ unsigned int ifdepth = 0;

for (;;) {
start:
@@ -265,51 +367,64 @@
CASE('\'', squote);
CASE('"', dquote);
CASE('#', pound);
+ if (ifdepth > 0)
+ goto start;
CASE('C', cee);
CASE('_', underscore);
goto start;

/* / */
slash:
- GETNEXT
- NOTCASE('*', __start);
+ GETNEXT NOTCASE('*', __start);
slash_star_dot_star:
GETNEXT
__slash_star_dot_star:
- NOTCASE('*', slash_star_dot_star);
+ NOTCASE('*', slash_star_dot_star);
- GETNEXT
- NOTCASE('/', __slash_star_dot_star);
+ GETNEXT NOTCASE('/', __slash_star_dot_star);
goto start;

/* '.*?' */
squote:
- GETNEXT
- CASE('\'', start);
+ GETNEXT CASE('\'', start);
- NOTCASE('\\', squote);
+ NOTCASE('\\', squote);
GETNEXT
goto squote;

/* ".*?" */
dquote:
- GETNEXT
- CASE('"', start);
+ GETNEXT CASE('"', start);
- NOTCASE('\\', dquote);
+ NOTCASE('\\', dquote);
GETNEXT
goto dquote;

/* #\s* */
pound:
- GETNEXT
- CASE(' ', pound);
- CASE('\t', pound);
+ GETNEXT SPACE(pound);
- CASE('i', pound_i);
+ CASE('i', pound_i);
+ if (ifdepth > 0) {
+ CASE('e', pound_e);
+ goto __start;
+ }
- CASE('d', pound_d);
+ CASE('d', pound_d);
- CASE('u', pound_u);
+ CASE('u', pound_u);
+ goto __start;
+
+/* #\s*e */
+pound_e:
+ GETNEXT NOTCASE('n', __start);
+ GETNEXT NOTCASE('d', __start);
+ GETNEXT NOTCASE('i', __start);
+ GETNEXT NOTCASE('f', __start);
+ ifdepth--;
goto __start;

/* #\s*i */
pound_i:
- GETNEXT NOTCASE('n', __start);
+ GETNEXT CASE('f', pound_if);
+ if (ifdepth > 0)
+ goto __start;
+
+ NOTCASE('n', __start);
GETNEXT NOTCASE('c', __start);
GETNEXT NOTCASE('l', __start);
GETNEXT NOTCASE('u', __start);
@@ -317,29 +432,36 @@
GETNEXT NOTCASE('e', __start);
goto pound_include;

+/* #\s*if */
+pound_if:
+ if (ifdepth > 0) {
+ ifdepth++;
+ goto __start;
+ }
+ GETNEXT NOTSPACE( __start);
+ GETNEXT NOTCASE('0', __start);
+ ifdepth++;
+ goto __start;
+
/* #\s*include\s* */
pound_include:
- GETNEXT
- CASE(' ', pound_include);
- CASE('\t', pound_include);
+ GETNEXT SPACE( pound_include);
map_dot = next;
- CASE('"', pound_include_dquote);
+ CASE('"', pound_include_dquote);
- CASE('<', pound_include_langle);
+ CASE('<', pound_include_langle);
goto __start;

/* #\s*include\s*"(.*)" */
pound_include_dquote:
- GETNEXT
- CASE('\n', start);
+ GETNEXT CASE('\n', start);
- NOTCASE('"', pound_include_dquote);
+ NOTCASE('"', pound_include_dquote);
handle_include(1, map_dot, next - map_dot - 1);
goto start;

/* #\s*include\s*<(.*)> */
pound_include_langle:
- GETNEXT
- CASE('\n', start);
+ GETNEXT CASE('\n', start);
- NOTCASE('>', pound_include_langle);
+ NOTCASE('>', pound_include_langle);
handle_include(0, map_dot, next - map_dot - 1);
goto start;

@@ -362,10 +484,7 @@

/* #\s*(define|undef)\s*CONFIG_(\w*) */
pound_define_undef:
- GETNEXT
- CASE(' ', pound_define_undef);
- CASE('\t', pound_define_undef);
-
+ GETNEXT SPACE( pound_define_undef);
NOTCASE('C', __start);
GETNEXT NOTCASE('O', __start);
GETNEXT NOTCASE('N', __start);
\
 
 \ /
  Last update: 2005-03-22 13:52    [from the cache]
©2003-2014 Jasper Spaans. Advertise on this site