Scanner segfault: Works fine on i686, but fails on x86_64

Glenn <[email protected]> Thu, 13 Feb 2014 18:53:50 -0700
Newsgroups gmane.comp.lex.flex.general
Message-ID <[email protected]>
--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

--
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

--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="spewage.txt"

#########################################################################
# 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

--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="xtpanel_scan.l"

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);
}

--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="test.xt"

button={
    label="  QUIT  "
    background=lightblue
}
   

--AhhlLboLdkugWU4S
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
help-flex mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/help-flex

--AhhlLboLdkugWU4S--