-- Greetings Flexoids, I'm trying to debug a flex scanner segfault issue in a very old program (not mine) about which I know essentially nothing of its internals, just trying to build it. To add to the fun, I know very little about flex.
The good news is that the scanner builds and works just fine when built and run a 32b i686 box. The segfaults occurs only when it is built and run on an x86_64. The segfault occurs at the scanner line "*yy_cp = (yy_hold_char);". Goolging suggests that this is a common point of failure, related (I think?) to overrunning a buffer which is expected to be null-terminated but isn't. However, I was unable to make any further headway in determining more than this (and not even sure the above is correct.) Also googled for complaints about similar 32b/64b flex issues in general, i.e. anything that might give a hint as to why a particular scanner might work for 32b but not 64b. No joy on that either. Could someone here perhaps cast an expert eye at it, suggest some things to try in order to narrow down the issue? Any help would be greatly appreciated. Attached are three relevant files: spewage.txt: Scanner build lines (flex, and subsequent gcc), and the output from a gdb session in which it segfaults. xtpanel_scan.l: Scanner definition test.xt: The scanner input file on which the segfault occurs. If anything else would be useful, just let me know. TIA, Glenn
######################################################################### # Commands executed (by Makefile) to build lex.yy.c: ######################################################################### flex -X -v -T xtpanel_scan.l gcc -g -fno-strength-reduce -I/usr/include/X11 -Dlinux \ -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -D_XOPEN_SOURCE \ -D_BSD_SOURCE -D_SVID_SOURCE -DFUNCPROTO=15 -DNARROWPROTO \ -DSYS_XTPANELDIR=\"/usr/local/xtpanel\" -DXPM lex.yy.c mv lex.yy.o xtpanel_scan.o ######################################################################### # Output from flex -T during above build: ######################################################################### %s'FOUNDTAG'%% 1 <'FOUNDTAG'>('([^']*'')*[^']*[']) 2 <'FOUNDTAG'>(`([^`]*``)*[^`]*[`]) 3 <'FOUNDTAG'>(\"([^\"]*\"\")*[^\"]*[\"]) 4 <'FOUNDTAG'>[^'\"]([^ \011\012\{\}])* 5 (([A-Za-z])([A-Za-z0-9_\-])*=\{) 6 ([ \011])(([A-Za-z])([A-Za-z0-9_\-])*=\{) 7 (([A-Za-z])([A-Za-z0-9_\-])*=)/[^ \011\012\{\}] 8 (([A-Za-z])([A-Za-z0-9_\-])*=)([ \011\012]) 9 (\}) 10 (\{) 11 ([ \011\012])+ 12 ^![^\012]* 13 ![^\012]* 14 . 15 End Marker ********** beginning dump of nfa with start state 135 state # 1 257: 0, 0 state # 2 257: 0, 0 state # 3 257: 0, 0 state # 4 257: 0, 0 state # 5 39: 14, 0 state # 6 -1: 7, 0 state # 7 257: 6, 8 state # 8 257: 10, 0 state # 9 257: 6, 8 state # 10 39: 11, 0 state # 11 39: 12, 0 state # 12 257: 9, 13 state # 13 257: 18, 0 state # 14 257: 9, 13 state # 15 -2: 16, 0 state # 16 257: 15, 17 state # 17 257: 19, 0 state # 18 257: 15, 17 state # 19 -3: 20, 0 state # 20 257: 0, 0 [1] state # 21 257: 3, 5 state # 22 96: 31, 0 state # 23 -4: 24, 0 state # 24 257: 23, 25 state # 25 257: 27, 0 state # 26 257: 23, 25 state # 27 96: 28, 0 state # 28 96: 29, 0 state # 29 257: 26, 30 state # 30 257: 35, 0 state # 31 257: 26, 30 state # 32 -5: 33, 0 state # 33 257: 32, 34 state # 34 257: 36, 0 state # 35 257: 32, 34 state # 36 -6: 37, 0 state # 37 257: 0, 0 [2] state # 38 257: 21, 22 state # 39 34: 48, 0 state # 40 -7: 41, 0 state # 41 257: 40, 42 state # 42 257: 44, 0 state # 43 257: 40, 42 state # 44 34: 45, 0 state # 45 34: 46, 0 state # 46 257: 43, 47 state # 47 257: 52, 0 state # 48 257: 43, 47 state # 49 -8: 50, 0 state # 50 257: 49, 51 state # 51 257: 53, 0 state # 52 257: 49, 51 state # 53 -9: 54, 0 state # 54 257: 0, 0 [3] state # 55 257: 38, 39 state # 56 -10: 60, 0 state # 57 -11: 58, 0 state # 58 257: 57, 59 state # 59 257: 0, 0 [4] state # 60 257: 57, 59 state # 61 257: 55, 56 state # 62 -12: 66, 0 state # 63 -13: 64, 0 state # 64 257: 63, 65 state # 65 257: 67, 0 state # 66 257: 63, 65 state # 67 61: 68, 0 state # 68 123: 69, 0 state # 69 257: 0, 0 [5] state # 70 257: 1, 62 state # 71 257: 61, 62 state # 72 -14: 73, 0 state # 73 -15: 77, 0 state # 74 -16: 75, 0 state # 75 257: 74, 76 state # 76 257: 78, 0 state # 77 257: 74, 76 state # 78 61: 79, 0 state # 79 123: 80, 0 state # 80 257: 0, 0 [6] state # 81 257: 70, 72 state # 82 257: 71, 72 state # 83 -17: 87, 0 state # 84 -18: 85, 0 state # 85 257: 84, 86 state # 86 257: 88, 0 state # 87 257: 84, 86 state # 88 61: 89, 0 state # 89 -19: 90, 0 state # 90 257: 0, 0 [7] state # 91 257: 81, 83 state # 92 257: 82, 83 state # 93 -20: 97, 0 state # 94 -21: 95, 0 state # 95 257: 94, 96 state # 96 257: 98, 0 state # 97 257: 94, 96 state # 98 61: 99, 0 state # 99 -22: 100, 0 state # 100 257: 0, 0 [8] state # 101 257: 91, 93 state # 102 257: 92, 93 state # 103 125: 104, 0 state # 104 257: 0, 0 [9] state # 105 257: 101, 103 state # 106 257: 102, 103 state # 107 123: 108, 0 state # 108 257: 0, 0 [10] state # 109 257: 105, 107 state # 110 257: 106, 107 state # 111 -23: 112, 0 state # 112 257: 111, 0 [11] state # 113 257: 109, 111 state # 114 257: 110, 111 state # 115 33: 119, 0 state # 116 -24: 117, 0 state # 117 257: 116, 118 state # 118 257: 0, 0 [12] state # 119 257: 116, 118 state # 120 257: 2, 115 state # 121 257: 4, 115 state # 122 33: 126, 0 state # 123 -25: 124, 0 state # 124 257: 123, 125 state # 125 257: 0, 0 [13] state # 126 257: 123, 125 state # 127 257: 113, 122 state # 128 257: 114, 122 state # 129 -26: 130, 0 state # 130 257: 0, 0 [14] state # 131 257: 127, 129 state # 132 257: 128, 129 state # 133 -28: 134, 0 state # 134 257: 0, 0 [15] state # 135 257: 131, 133 state # 136 257: 132, 133 ********** end of dump DFA Dump: state # 1: 1 6 2 7 3 8 4 9 5 6 6 6 7 6 8 6 9 10 10 6 11 11 12 12 state # 2: 1 6 2 7 3 8 4 13 5 6 6 6 7 6 8 6 9 10 10 6 11 11 12 12 state # 3: 1 14 2 15 3 16 4 17 5 18 6 19 7 14 8 14 9 20 10 21 11 22 12 23 state # 4: 1 14 2 15 3 16 4 24 5 18 6 19 7 14 8 14 9 20 10 21 11 22 12 23 state # 5: state # 6: state # 7: 2 25 3 25 9 26 state # 8: 2 25 3 25 state # 9: 1 27 2 27 4 27 5 27 6 27 7 27 8 27 9 27 10 27 11 27 12 27 state # 10: 7 28 8 29 9 28 state # 11: state # 12: state # 13: 1 30 2 30 4 30 5 30 6 30 7 30 8 30 9 30 10 30 11 30 12 30 state # 14: 1 31 4 31 5 31 6 31 7 31 8 31 9 31 10 31 state # 15: 1 31 2 25 3 25 4 31 5 31 6 31 7 31 8 31 9 32 10 31 state # 16: 1 31 2 25 3 25 4 31 5 31 6 31 7 31 8 31 9 31 10 31 state # 17: 1 33 2 27 4 33 5 33 6 33 7 33 8 33 9 33 10 33 11 27 12 27 state # 18: 1 34 2 34 3 34 4 34 5 35 6 34 7 34 8 34 9 34 10 34 11 34 12 34 state # 19: 1 36 2 36 3 36 4 36 5 36 6 37 7 36 8 36 9 36 10 36 11 36 12 36 state # 20: 1 31 4 31 5 31 6 31 7 38 8 39 9 38 10 31 state # 21: 1 40 2 41 3 41 4 40 5 40 6 40 7 40 8 40 9 40 10 42 11 41 12 41 state # 22: 1 31 4 31 5 31 6 31 7 31 8 31 9 31 10 31 state # 23: 1 31 4 31 5 31 6 31 7 31 8 31 9 31 10 31 state # 24: 1 43 2 30 4 43 5 43 6 43 7 43 8 43 9 43 10 43 11 30 12 30 state # 25: 2 25 3 25 state # 26: 7 44 8 45 9 44 state # 27: 1 27 2 27 4 27 5 27 6 27 7 27 8 27 9 27 10 27 11 27 12 27 state # 28: 7 28 8 29 9 28 state # 29: 1 46 2 47 3 47 4 46 5 46 6 46 7 46 8 46 9 46 10 46 11 48 state # 30: 1 30 2 30 4 30 5 30 6 30 7 30 8 30 9 30 10 30 11 30 12 30 state # 31: 1 31 4 31 5 31 6 31 7 31 8 31 9 31 10 31 state # 32: 1 31 4 31 5 31 6 31 7 49 8 50 9 49 10 31 state # 33: 1 33 2 27 4 33 5 33 6 33 7 33 8 33 9 33 10 33 11 27 12 27 state # 34: 1 34 2 34 3 34 4 34 5 35 6 34 7 34 8 34 9 34 10 34 11 34 12 34 state # 35: 5 51 state # 36: 1 36 2 36 3 36 4 36 5 36 6 37 7 36 8 36 9 36 10 36 11 36 12 36 state # 37: 6 52 state # 38: 1 31 4 31 5 31 6 31 7 38 8 39 9 38 10 31 state # 39: 1 53 2 47 3 47 4 53 5 53 6 53 7 53 8 53 9 53 10 53 11 48 state # 40: 1 40 2 41 3 41 4 40 5 40 6 40 7 40 8 40 9 40 10 42 11 41 12 41 state # 41: 1 41 2 41 3 41 4 41 5 41 6 41 7 41 8 41 9 41 10 54 11 41 12 41 state # 42: 1 31 4 31 5 31 6 31 7 31 8 31 9 31 10 55 state # 43: 1 43 2 30 4 43 5 43 6 43 7 43 8 43 9 43 10 43 11 30 12 30 state # 44: 7 44 8 45 9 44 state # 45: 11 56 state # 46: state # 47: state # 48: state # 49: 1 31 4 31 5 31 6 31 7 49 8 50 9 49 10 31 state # 50: 1 31 4 31 5 31 6 31 7 31 8 31 9 31 10 31 11 56 state # 51: 1 34 2 34 3 34 4 34 5 35 6 34 7 34 8 34 9 34 10 34 11 34 12 34 state # 52: 1 36 2 36 3 36 4 36 5 36 6 37 7 36 8 36 9 36 10 36 11 36 12 36 state # 53: 1 31 4 31 5 31 6 31 7 31 8 31 9 31 10 31 state # 54: 10 57 state # 55: 1 40 2 41 3 41 4 40 5 40 6 40 7 40 8 40 9 40 10 42 11 41 12 41 state # 56: state # 57: 1 41 2 41 3 41 4 41 5 41 6 41 7 41 8 41 9 41 10 54 11 41 12 41 state # 5 accepts: [16] state # 6 accepts: [14] state # 7 accepts: [11] state # 8 accepts: [11] state # 9 accepts: [13] state # 10 accepts: [14] state # 11 accepts: [10] state # 12 accepts: [9] state # 13 accepts: [12] state # 14 accepts: [4] state # 15 accepts: [4] state # 16 accepts: [4] state # 17 accepts: [4] state # 18 accepts: [14] state # 19 accepts: [14] state # 20 accepts: [4] state # 21 accepts: [4] state # 22 accepts: [4] state # 23 accepts: [4] state # 24 accepts: [4] state # 25 accepts: [11] state # 27 accepts: [13] state # 30 accepts: [12] state # 31 accepts: [4] state # 32 accepts: [4] state # 33 accepts: [4] state # 35 accepts: [3] state # 37 accepts: [1] state # 38 accepts: [4] state # 39 accepts: [4] state # 40 accepts: [4] state # 42 accepts: [2] state # 43 accepts: [4] state # 46 accepts: [7] state # 47 accepts: [8] state # 48 accepts: [5] state # 49 accepts: [4] state # 50 accepts: [4] state # 53 accepts: [4] state # 54 accepts: [2] state # 55 accepts: [4] state # 56 accepts: [6] Equivalence Classes: \000 = -1 ' ' = 2 @ = 1 ` = 10 \200 = 1 \240 = 1 \300 = 1 \340 = 1 \001 = 1 ! = 4 A = 9 a = 9 \201 = 1 \241 = 1 \301 = 1 \341 = 1 \002 = 1 " = 5 B = 9 b = 9 \202 = 1 \242 = 1 \302 = 1 \342 = 1 \003 = 1 # = 1 C = 9 c = 9 \203 = 1 \243 = 1 \303 = 1 \343 = 1 \004 = 1 $ = 1 D = 9 d = 9 \204 = 1 \244 = 1 \304 = 1 \344 = 1 \005 = 1 % = 1 E = 9 e = 9 \205 = 1 \245 = 1 \305 = 1 \345 = 1 \006 = 1 & = 1 F = 9 f = 9 \206 = 1 \246 = 1 \306 = 1 \346 = 1 \a = 1 ' = 6 G = 9 g = 9 \207 = 1 \247 = 1 \307 = 1 \347 = 1 \b = 1 ( = 1 H = 9 h = 9 \210 = 1 \250 = 1 \310 = 1 \350 = 1 \t = 2 ) = 1 I = 9 i = 9 \211 = 1 \251 = 1 \311 = 1 \351 = 1 \n = 3 * = 1 J = 9 j = 9 \212 = 1 \252 = 1 \312 = 1 \352 = 1 \v = 1 + = 1 K = 9 k = 9 \213 = 1 \253 = 1 \313 = 1 \353 = 1 \f = 1 , = 1 L = 9 l = 9 \214 = 1 \254 = 1 \314 = 1 \354 = 1 \r = 1 - = 7 M = 9 m = 9 \215 = 1 \255 = 1 \315 = 1 \355 = 1 \016 = 1 . = 1 N = 9 n = 9 \216 = 1 \256 = 1 \316 = 1 \356 = 1 \017 = 1 / = 1 O = 9 o = 9 \217 = 1 \257 = 1 \317 = 1 \357 = 1 \020 = 1 0 = 7 P = 9 p = 9 \220 = 1 \260 = 1 \320 = 1 \360 = 1 \021 = 1 1 = 7 Q = 9 q = 9 \221 = 1 \261 = 1 \321 = 1 \361 = 1 \022 = 1 2 = 7 R = 9 r = 9 \222 = 1 \262 = 1 \322 = 1 \362 = 1 \023 = 1 3 = 7 S = 9 s = 9 \223 = 1 \263 = 1 \323 = 1 \363 = 1 \024 = 1 4 = 7 T = 9 t = 9 \224 = 1 \264 = 1 \324 = 1 \364 = 1 \025 = 1 5 = 7 U = 9 u = 9 \225 = 1 \265 = 1 \325 = 1 \365 = 1 \026 = 1 6 = 7 V = 9 v = 9 \226 = 1 \266 = 1 \326 = 1 \366 = 1 \027 = 1 7 = 7 W = 9 w = 9 \227 = 1 \267 = 1 \327 = 1 \367 = 1 \030 = 1 8 = 7 X = 9 x = 9 \230 = 1 \270 = 1 \330 = 1 \370 = 1 \031 = 1 9 = 7 Y = 9 y = 9 \231 = 1 \271 = 1 \331 = 1 \371 = 1 \032 = 1 : = 1 Z = 9 z = 9 \232 = 1 \272 = 1 \332 = 1 \372 = 1 \033 = 1 ; = 1 [ = 1 { = 11 \233 = 1 \273 = 1 \333 = 1 \373 = 1 \034 = 1 < = 1 \ = 1 | = 1 \234 = 1 \274 = 1 \334 = 1 \374 = 1 \035 = 1 = = 8 ] = 1 } = 12 \235 = 1 \275 = 1 \335 = 1 \375 = 1 \036 = 1 > = 1 ^ = 1 ~ = 1 \236 = 1 \276 = 1 \336 = 1 \376 = 1 \037 = 1 ? = 1 _ = 7 \177 = 1 \237 = 1 \277 = 1 \337 = 1 \377 = 1 Meta-Equivalence Classes: 1 = 1 2 = 2 3 = 3 4 = 1 5 = 1 6 = 1 7 = 4 8 = 4 9 = 5 10 = 1 11 = 6 12 = 7 flex version 2.5.37 usage statistics: scanner options: -XvIT8 -Cem 138/2000 NFA states 57/1000 DFA states (333 words) 14 rules Compressed tables always back-up Beginning-of-line patterns used 2/40 start conditions 92 epsilon states, 60 double epsilon states 28/100 character classes needed 496/500 words of storage, 0 reused 422 state/nextstate pairs created 119/303 unique/duplicate transitions 71/1000 base-def entries created 201/2000 (peak 270) nxt-chk entries created 98/2500 (peak 168) template nxt-chk entries created 34 empty table entries 24 protos created 14 templates created, 34 uses 12/256 equivalence classes created 7/256 meta-equivalence classes created 4 (1 saved) hash collisions, 67 DFAs equal 0 sets of reallocations needed 812 total table entries needed ######################################################################### # Run program under gdb, observe segfault: ######################################################################### $ gdb ./xtpanel Reading symbols from /home/xyz/src/xtpanel-3.24G3/xtpanel...done. (gdb) run -file test.xt Starting program: /home/xyz/src/xtpanel-3.24G3/./xtpanel -file test.xt xtpanel_scan button={ label=" QUIT " background=lightblue } xtpanel_scan_end Program received signal SIGSEGV, Segmentation fault. 0x00000000004098b7 in yylex () at lex.yy.c:873 873 *yy_cp = (yy_hold_char); # # Backtrace: # (gdb) bt #0 0x00000000004098b7 in yylex () at lex.yy.c:873 #1 0x000000000040bf24 in xtpanel_scan ( buffer=0x6564a0 "button={\n label=\" QUIT \"\n background=lightblue\n}", root=0x6517d0) at xtpanel_scan.l:313 #2 0x0000000000405288 in parse_file (file=0x656260, root=0x6517d0) at parse.c:378 #3 0x000000000040518d in parse_file_named (filename=0x7fffffffe90f "test.xt", root=0x6517d0, use_cpp=0, cpp_args=0x655e50 "") at parse.c:338 #4 0x000000000040465b in parse_args (argc=0, argv=0x7fffffffe5e0, root=0x6517d0) at parse.c:167 #5 0x000000000041abc3 in xtp_init_app (argc=2, argv=0x7fffffffe5d0) at xtpanel_init.c:157 #6 0x0000000000403d42 in main (argc=3, argv=0x7fffffffe5c8) at main.c:53
NONSEPAR [^ \t\n\{\}] WHITE [ \t\n] ALPHA [A-Za-z] ALPHANUM [A-Za-z0-9_-] TAG {ALPHA}{ALPHANUM}*= TAGBRACE {ALPHA}{ALPHANUM}*=\{ SQ \'([^']*\'\')*[^']*['] DQ \"([^"]*\"\")*[^"]*["] BQ \`([^`]*\`\`)*[^`]*[`] LEFT \{ RIGHT \} %{ /* * Copyright 1992 the Board of Trustees of the Leland Stanford Junior * University. Official permission to use this software is included in * the documentation. It authorizes you to use this file for any * non-commercial purpose, provided that this copyright notice is not * removed and that any modifications made to this file are commented * and dated in the style of the example below. */ /* * * source file: ./xtpanel/xtpanel-scan.l * * Steve Cole, Dave Nichols (SEP), August 31 1992 * Inserted this sample edit history entry. * Please log any further modifications made to this file: * Steve Cole, Dave Nichols (SEP), November 20 1992 - version 2.00 * 1) added new objects: toggle, scrollbar, graph. * 2) added new actions: ASSIGN, SET. * 3) objects can have multiple actions. * 4) backquoted strings in actions get executed at action time. * Steve Losen (s...@virginia.edu) 3 Mar 1993 * introduced `` as an escaped backquote. * Dave Nichols (SEP), Sept 2 1993 - * added support for using flex * Dave Nichols (SEP), Nov 16 1993 - * Use X11/Xos.h, this requires undefining "input" before * the include as the X11 includes have a variable called input. * Dave Nichols (Geco-Prakla), Sept 29 1995 - * Don't redefine yylook as a macro, gcc complains about later * definition. */ /* lexical scanning for xtpanel */ #define DEBUG #undef input #include <ctype.h> #include <stdio.h> #include <string.h> #include <X11/Xos.h> #if defined(SVR4) || defined(SYSV) #define bcopy(a,b,c) memcpy(b,a,c) #endif #include "tree.h" #include "eval_command.h" #ifndef MIN #define MIN(A,B) (A<B?A:B) #endif #ifndef MAX #define MAX(A,B) (A>B?A:B) #endif #define MAX_NEST 20 static int stack_ptr = -1; static char *input_buf; static char *input_buf_start; static char *input_buf_end; static entry *entry_stack[MAX_NEST]; #ifdef FLEX_SCANNER /* one character at a time to ensure accurate error reporting */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ { if( input_buf == input_buf_end+1 ) { \ result=0; \ }else{ \ result=1;\ *buf = *input_buf;\ input_buf++; \ } \ } /* result = MIN( max_size, input_buf_end-input_buf+1 ); \ */ /* bcopy(input_buf,buf,result); \ */ /* input_buf += result; \ */ /* }\ */ /* } */ #undef yywrap #else #undef input #define input() ((int) *(input_buf++)) #undef unput /* The redundant =(c) insures side effects of expressions occur */ #define unput(c) (*(--(input_buf))=(c)) /* define the look ahead buffer size to something big * This is needed in case they have a very big text * string in quotes. */ #undef YYLMAX #define YYLMAX 50000 char my_yytmp[YYLMAX]; #define yywrap xtpanel_wrap #define yylex xtpanel_lexscan #define yylook xtpanel_yylook #endif entry *tree_ent; entry *treetop; int len; int left=0; static void syntax_err(); static int massage(); extern int bad_obj_syntax(); extern int bad_attr_syntax(); /* template check */ extern void new_template(); void template_check( a, b ) entry* a, *b; { if( !strcmp(a->tag,"template") && !strcmp(b->tag,"name" )) new_template( b->value ); } %} %S FOUNDTAG %% <FOUNDTAG>{SQ} { len = yyleng-2; tree_ent->value=malloc(len+1); len = massage(yytext+1,tree_ent->value,len,yytext[0]); tree_ent->value[len]='\0'; add_child( treetop, tree_ent ); template_check( treetop, tree_ent ); #ifdef DEBUG fprintf(stderr,"<FOUNDTAG>{SQ}\n"); fprintf(stderr,"%s\n",tree_ent->value); #endif BEGIN 0; } <FOUNDTAG>{BQ} { /* backquotes are now evaluated in get_value */ len=yyleng; tree_ent->value=malloc(len+1); bcopy(yytext,tree_ent->value,len+1); tree_ent->value[len]='\0'; add_child( treetop, tree_ent ); template_check( treetop, tree_ent ); #ifdef DEBUG fprintf(stderr,"<FOUNDTAG>{BQ}\n"); fprintf(stderr,"%s\n",tree_ent->value); #endif BEGIN 0; } <FOUNDTAG>{DQ} { len = yyleng-2; tree_ent->value=malloc(len+1); len = massage(yytext+1,tree_ent->value,len,yytext[0]); tree_ent->value[len]='\0'; add_child( treetop, tree_ent ); template_check( treetop, tree_ent ); #ifdef DEBUG fprintf(stderr,"<FOUNDTAG>{DQ}\n"); fprintf(stderr,"%s\n",tree_ent->value); #endif BEGIN 0; } <FOUNDTAG>[^'"]{NONSEPAR}* { len=yyleng; tree_ent->value=malloc(len+1); bcopy(yytext,tree_ent->value,len+1); tree_ent->value[len]='\0'; add_child( treetop, tree_ent ); template_check( treetop, tree_ent ); #ifdef DEBUG fprintf(stderr,"<FOUNDTAG>{NONSEPAR}\n"); fprintf(stderr,"%s\n",tree_ent->value); #endif BEGIN 0; } {TAGBRACE} { /* start of a new level of braces */ tree_ent = new_entry( yytext, get_taglen(yytext,yyleng-1)); /* check that this is a valid sublevel name */ if( bad_obj_syntax( treetop, tree_ent ) ){ syntax_err("Invalid tag name"); } push_entry( tree_ent ); left++; #ifdef DEBUG fprintf(stderr,"{TAGBRACE}\n"); fprintf(stderr,"%s\n",tree_ent->tag); #endif } ([ \t]){TAGBRACE} { /* start of a new level of braces */ tree_ent = new_entry( yytext+1, get_taglen(yytext+1,yyleng-2)); /* check that this is a valid sublevel name */ if( bad_obj_syntax( treetop, tree_ent ) ){ syntax_err("Invalid tag name"); } push_entry(tree_ent); left++; #ifdef DEBUG fprintf(stderr,"[ \\t]{TAGBRACE}\n"); fprintf(stderr,"%s\n",tree_ent->tag); #endif } {TAG}/{NONSEPAR} { tree_ent = new_entry( yytext, yyleng-1 ); /* check that this is a valid entry name */ if( bad_attr_syntax( treetop, tree_ent ) ){ syntax_err("Invalid tag name"); } #ifdef DEBUG fprintf(stderr,"{TAG}/{NONSEPAR}\n"); fprintf(stderr,"%s\n",tree_ent->tag); #endif BEGIN FOUNDTAG; } {TAG}{WHITE} { /* an empty tag */ syntax_err("unexpected empty field "); } {RIGHT} { /* end of a level of braces */ pop_entry(); left--; #ifdef DEBUG fprintf(stderr,"{RIGHT}\n"); #endif if( left<0 ) { syntax_err("unmatched right brace"); } } {LEFT} { /* found a left brace in the wrong context */ #ifdef DEBUG fprintf(stderr,"{LEFT}\n"); #endif syntax_err("left brace found in an unexpected place"); } {WHITE}+ { #ifdef DEBUG fprintf(stderr,"Ignored whitespace\n"); fprintf(stderr,"length %d\n",yyleng); #endif } ^\![^\n]* {/* skip comment lines */; #ifdef DEBUG fprintf(stderr,"Comment line\n"); #endif } \![^\n]* { /* comment not at start of line, allow for now */ #ifdef DEBUG fprintf(stderr,"Trailing comment\n"); #endif /* syntax_err("comment introducer not at start of line");*/ } . { #ifdef DEBUG fprintf(stderr,"Something unrecognised\n"); #endif syntax_err("unrecognisable construct"); } %% /* workhorse to decode xtpanel files; */ entry* xtpanel_scan( buffer, root ) char* buffer; entry* root; { extern int yylex(); #ifdef DEBUG fprintf(stderr,"xtpanel_scan\n%s\nxtpanel_scan_end\n",buffer); #endif /* note the input buffer should be null terminated */ input_buf = buffer; input_buf_start = input_buf; input_buf_end = input_buf + strlen(input_buf)-1 ; /* all the info we find will be stored under the root entry */ push_entry( root ); #ifdef FLEX_SCANNER yy_init=1; #endif yylex(); if( left > 0 ) { fprintf(stderr," %d unmatched left braces present \n",left); exit(-1); } if( left < 0 ) { fprintf(stderr," %d unmatched right braces present \n",-left); exit(-1); } } /* get the tag length from a string that may have spaces around the equal */ int get_taglen( str, len ) char *str; int len; { char *temp; int ret; temp = malloc( len+1); strncpy( temp, str, len ); temp[len]='\0'; ret= strcspn( temp, " =" ) ; free(temp); return ret; } /* print a syntax error, try and give them enough context to figure * out where it is */ static void syntax_err( message ) char *message; { char temp[41]; int lchar,rchar,nchar,i,j,linepos; /* print the error message */ fprintf(stderr,"\nSyntax Error: %s\n\n", message); /* back up to the character causing the error */ input_buf--; /* print enough characters on either side to give he user some context*/ lchar = MIN( 20, input_buf - input_buf_start ); rchar = MIN( 20, input_buf_end - input_buf); nchar = lchar+rchar+1; strncpy( temp, (input_buf-lchar), nchar ); temp[nchar] = '\0'; /* print stuff to the left of the point */ for( i=0; i<lchar; i++ ){ putc( temp[i], stderr ); if( temp[i] == '\n' ){ linepos=0; }else if( temp[i] == '\t' ){ linepos += 8; }else{ linepos++; } } /* print from the point up to the end or the next newline */ for( i=lchar; ( i<nchar && temp[i] != '\n' ) ; i++ ){ putc( temp[i], stderr ); } /* print the marker that points at the error */ putc( '\n', stderr ); for( j=0; j<linepos; j++ ){ putc( ' ', stderr ); } fprintf(stderr,"^--- error detected at text ending here (I think)\n",temp); /* print the rest of the text (if any ) */ for( j=i+1; j<nchar; j++ ){ putc( temp[j], stderr ); } putc( '\n', stderr ); exit(-1); } push_entry( ent ) entry* ent; { if( stack_ptr >=0 ) add_child( entry_stack[stack_ptr], ent ); stack_ptr++; if( stack_ptr >=MAX_NEST ){ fprintf(stderr," items nested too deeply, only %d levels supported\n", MAX_NEST); exit(-1); } entry_stack[stack_ptr] = ent; treetop = entry_stack[stack_ptr]; } pop_entry() { stack_ptr--; if( stack_ptr >= 0 ) treetop = entry_stack[stack_ptr] ; } int yywrap() { pop_entry(); if(stack_ptr < 0) return(1); return(0); } /* play with quoted strings and newlines etc. */ static int massage(string,out,len,quote) register char *string, *out; register int len, quote; { register int i,j; for(i=0,j=0; i<len-1; j++) { out[j]=string[i++]; if(out[j]==quote) /* compress doubled quotes */ if(string[i]==quote) i++; if(out[j]=='\\') { if(string[i]== 'n') { /* turn backslash n "\n" into a newline */ i++; out[j] = '\n'; }else if( string[i] == '\n' ){ /* remove backslash newline */ i++; j--; } } } if(i<len) out[j++] = string[i]; return(j); }
button={ label=" QUIT " background=lightblue }
_______________________________________________ help-flex mailing list help-flex@gnu.org https://lists.gnu.org/mailman/listinfo/help-flex