--
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 ([email protected]) 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
[email protected]
https://lists.gnu.org/mailman/listinfo/help-flex