File: gdescan.m

package info (click to toggle)
fis-gtm 6.3-007-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 36,284 kB
  • sloc: ansic: 328,861; asm: 5,182; csh: 5,102; sh: 1,918; awk: 291; makefile: 69; sed: 13
file content (149 lines) | stat: -rwxr-xr-x 6,648 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;								;
;	Copyright 2001, 2013 Fidelity Information Services, Inc	;
;								;
;	This source code contains the intellectual property	;
;	of its copyright holder(s), and is made available	;
;	under a license.  If you do not know the terms of	;
;	the license, please stop and do not read further.	;
;								;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdescan: ;scanner used by gdeparse
GETTOK
	n c,tmptok,tokisname
	; If -name has been seen, then change GETTOK to fetch next token (which is the actual name specification)
	;   by taking double-quotes into account. Same case with the next TWO tokens (not just one) in case of a
	;   RENAME command where two names are specified after the -name.
	; Otherwise use regular token scanning and search only for delimiters (e.g. " ", "," etc.)
	i ($get(toktype)=sep)&(ntoktype="TKIDENT")&$data(verb)&('$data(gqual))&$data(syntab(verb,"NAME")) d
	. ; check if the current token is -NAME. if so use special rules to parse the next token
	. s tmptok=ntoken
	. d checkkw^GDEPARSE(.tmptok,"object","syntab("""_verb_""")")
	. i tmptok="NAME" s tokisname=1
	e  i ($get(verb)="RENAME")&(($get(toktype)=sep)!$data(gqual)) s tokisname=1
	s token=ntoken,toktype=ntoktype
	; s dbgtoken($incr(dbgtokcnt))=token	; if uncommented, helps debug the GDE token parser
	d skipwhitespace
	s c=$ze(comline,cp)
	i ($c(10)=c)!($c(13)=c) s c="",cp=$zl(comline),ntoktype="TKEOL" d @ntoktype q
	s ntoktype=$s($d(tokens(c)):tokens(c),1:"TKIDENT")
	; If "gqual" is not yet filled in, it means we are still parsing either the "verb" or "gqual" but not "lqual".
	; If we see a double-quote at the start while in this state, parse the token using TKIDENT (and not TKSTRLIT
	; as we dont expect strings in this context).
	i (ntoktype="TKSTRLIT")&('$data(gqual)) s ntoktype="TKIDENT" d TKIDENTspacedelims q
	; Similarly if tokisname is TRUE, then parse the next token as a name-specification
	i $data(tokisname)  d TKIDENTspacedelims q
	d @ntoktype
	q
shotoks: ; for debugging only
	w !,"  toktype: ",toktype,?24," token: '",token,"'"
	w ?48," ntoktype: ",ntoktype,?72,"ntoken: '",ntoken,"'"
	q
skipwhitespace
	n i
	f i=0:1 s c=$ze(comline,cp+i) q:(c'=" ")&(c'=TAB)
	s cp=cp+i
	q
TKIDENT
	; if not parsing a list, a "=" is followed by a token that could have special characters (like "=" or "," or "-" etc.)
	; in this case we dont want these special characters to terminate the parse. Only a whitespace should terminate it.
	; if parsing inside a list, a "," or ")" or "=" could terminate the parse. So we cannot use the whitespace-only parse
	; logic in that case.
	i (toktype="TKEQUAL")&'$data(listparsing) d TKIDENTspacedelims q
	; by similar logic, if "gqual" is not yet filled in, and we did not see a - as the previous token, it means we are
	; parsing the "gqual". In that case, end the parse only when whitespace is encountered, not if "=" or "," is seen.
	i (toktype'=sep)&'$data(gqual) d TKIDENTspacedelims q
	n i
	d tokscan(.tokendelim)
	q
TKIDENTspacedelims
	d tokscan(.spacedelim)
	q
tokscan:(delim)
	n i,c
	i '$data(tokisname) d
	. f i=0:1 s c=$ze(comline,cp+i) q:$data(delim(c))
	e  d
	. ; About to parse the token following a -name. Take double-quotes into account.
	. ; Any delimiter that comes inside a double-quote does NOT terminate the scan/parse.
	. ; Implement the following DFA (Deterministic Finite Automaton)
	. ;	  State 0 --> next char is     a double-quote --> State 1
	. ;	  State 0 --> next char is NOT a double-quote --> State 0
	. ;	  State 1 --> next char is     a double-quote --> State 2
	. ;	  State 1 --> next char is NOT a double-quote --> State 1
	. ;	  State 2 --> next char is     a double-quote --> State 1
	. ;	  State 2 --> next char is NOT a double-quote --> State 0
	. ; Also note down (in NAMEsubs) the columns where LPAREN, COMMA and COLON appear. Later used in NAME^GDEPARSE
	. n quotestate,parenstate,errstate,quitloop
	. s quotestate=0,parenstate=0,errstate=""
	. k NAMEsubs ; this records the column where subscript delimiters COMMA or COLON appear in the name specification
	. k NAMEtype
	. s NAMEtype="POINT",NAMEsubs=0,quitloop=0
	. f i=0:1 s c=$ze(comline,cp+i) q:(c="")  d  q:quitloop
	. . i c="""" s quotestate=$s(quotestate=1:2,1:1)
	. . e        s quotestate=$s(quotestate=2:0,1:quotestate) i 'quotestate d
	. . . i $data(delim(c)) s quitloop=1 q
	. . . i (parenstate=2) i '$zl(errstate) s errstate="NAMRPARENNOTEND"
	. . . i (c="(") d
	. . . . i parenstate s parenstate=parenstate+2  q   ; nested parens
	. . . . s parenstate=1
	. . . . s NAMEsubs($incr(NAMEsubs))=(i+2)
	. . . i (c=",") d
	. . . . i 'parenstate i '$zl(errstate) s errstate="NAMLPARENNOTBEG"
	. . . . i (1'=parenstate) q   ; nested parens
	. . . . i NAMEtype="RANGE" i '$zl(errstate) s errstate="NAMRANGELASTSUB"
	. . . . s NAMEsubs($incr(NAMEsubs))=(i+2)
	. . . i c=":" d
	. . . . i 'parenstate i '$zl(errstate) s errstate="NAMLPARENNOTBEG"
	. . . . i NAMEtype="RANGE" i '$zl(errstate) s errstate="NAMONECOLON"
	. . . . s NAMEsubs($incr(NAMEsubs))=(i+2),NAMEtype="RANGE"
	. . . i c=")" d
	. . . . i 'parenstate i '$zl(errstate) s errstate="NAMLPARENNOTBEG"
	. . . . i (1'=parenstate) s parenstate=parenstate-2 q   ; nested parens
	. . . . s parenstate=2
	. . . . s NAMEsubs($incr(NAMEsubs))=(i+2)
	. i quotestate i '$zl(errstate) s errstate="STRMISSQUOTE"
	. i (1=parenstate)!(2<parenstate) i '$zl(errstate) s errstate="NAMRPARENMISSING"
	. i $zl(errstate) zm gdeerr(errstate):$ze(comline,cp,cp+i-1)
	. i 'NAMEsubs s NAMEsubs($incr(NAMEsubs))=i+2
	i c="" d
	. ; check if tail of last token in line contains $c(13,10) and if so remove it
	. ; this keeps V61 GDE backward compatible with V60 GDE
	. n j
	. f j=1:1 s c=$ze(comline,cp+i-j) q:($c(10)'=c)&($c(13)'=c)
	. s i=i-j+1
	s ntoken=$ze(comline,cp,cp+i-1),cp=cp+i
	d skipwhitespace
	i (ntoken="!") d TKEXCLAM	; if found a ! instead of a TKIDENT type token, set ntoktype to TKEOL
	q
TKSTRLIT
	n i,len
	s len=$zl(comline)
	f i=1:1:(len-cp) q:$ze(comline,cp+i)=""""
	i (i=(len-cp))&($ze(comline,cp+i)'="""") zm gdeerr("STRMISSQUOTE"):$ze(comline,cp,cp+i)
	s ntoken=$ze(comline,cp+1,cp+i-1),cp=cp+i+1
	d skipwhitespace
	q
TKAT
TKCOMMA
TKDASH ; see below for more UNIXy alternative
TKEQUAL
TKLPAREN
TKRPAREN
TKSLASH
	s ntoken=c,cp=cp+1
	i (ntoktype="TKRPAREN") d skipwhitespace
	q
TKEXCLAM
	s ntoktype="TKEOL"
	s ntoken=""
	s cp=$zl(comline)
	q
;TKDASH - more UNIXy handling disabled for compatibility with other utilities
	s ntoken=c,cp=cp+1
	i sep="TKDASH",$ze(comline,cp)?1A s c=$ze(comline,cp-2) i c=" "!(c=TAB) q
	zm gdeerr("ILLCHAR"):"-"
	q
TKEOL
	s ntoken=""
	q