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 | #include "extern.h" |
30 | |
31 | PUBLIC int |
32 | Parse_macro( buffer, flag ) |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | char *buffer; |
40 | int flag; |
41 | { |
42 | char *result; |
43 | TKSTR input; |
44 | HASHPTR hv; |
45 | int operator; |
46 | char *tok1; |
47 | char *tok2; |
48 | int toklen; |
49 | |
50 | DB_ENTER( "Parse_macro" ); |
51 | |
52 | SET_TOKEN( &input, buffer )(&input)->tk_str = (buffer); (&input)->tk_cchar = *(buffer); (&input)->tk_quote = 1;; |
53 | tok1 = Get_token( &input, "=+:*!?", 0 ); |
54 | |
55 | operator=Macro_op(tok1); |
56 | if( operator ) { |
| |
57 | CLEAR_TOKEN( &input )*(&input)->tk_str = (&input)->tk_cchar; |
58 | Error( "Assignment without macro name: [%s].", buffer ); |
59 | DB_RETURN( 1 )return (1); |
60 | } |
61 | |
62 | tok1 = DmStrDup(tok1); |
63 | tok2 = Get_token( &input, "=+:*!?", 2 ); |
64 | if( !(operator = Macro_op(tok2)) || !strcmp(tok1,".SETDIR") ) { |
| |
65 | CLEAR_TOKEN( &input )*(&input)->tk_str = (&input)->tk_cchar; |
66 | FREE(tok1)free((char*)(tok1)); |
67 | DB_RETURN(0)return (0); |
68 | } |
69 | |
70 | tok2 = Expand(tok1); FREE(tok1)free((char*)(tok1)); tok1 = tok2; |
71 | if ( !(toklen = strlen(tok1)) ) { |
| |
72 | Warning( "Empty macro name after expansion: [%s].", buffer ); |
73 | } |
74 | |
75 | |
76 | if ( toklen == 1 && strchr("{()}", tok1[0]) ) { |
77 | CLEAR_TOKEN( &input )*(&input)->tk_str = (&input)->tk_cchar; |
78 | Fatal( "Syntax error in macro assignment [%s]. The following characters cannot be used as single letter macro names: '{()}'.", buffer ); |
79 | } |
80 | |
81 | |
82 | if ( strchr(tok1, ':') ) { |
| |
83 | CLEAR_TOKEN( &input )*(&input)->tk_str = (&input)->tk_cchar; |
84 | Fatal( "Syntax error in macro assignment [%s]. The character ':' is not allowed in macro names.", buffer ); |
85 | } |
86 | |
87 | tok2 = Get_token(&input, NIL( char )((char*)((void*)0)), FALSE0); |
88 | |
89 | |
90 | if ( operator & M_OP_SI32 ) { |
| |
91 | flag |= M_FORCE0x0080|M_MULTI0x0004; |
92 | operator &= ~M_OP_SI32; |
93 | } |
94 | |
95 | switch( operator ) { |
| 6 | | Control jumps to 'case 17:' at line 138 | |
|
96 | case M_OP_PLCL7: |
97 | tok2 = Expand( tok2 ); |
98 | |
99 | |
100 | case M_OP_PL5: |
101 | |
102 | |
103 | |
104 | if( (hv = GET_MACRO(tok1)Get_name(tok1, Macs, 0)) == NIL(HASH)((HASH*)((void*)0)) || hv->ht_value == NIL(char)((char*)((void*)0)) ) |
105 | Def_macro( tok1, tok2, flag ); |
106 | else { |
107 | result = DmStrAdd( hv->ht_value, tok2, FALSE0 ); |
108 | Def_macro( tok1, result, flag ); |
109 | FREE( result )free((char*)(result)); |
110 | } |
111 | if( operator == M_OP_PLCL7 ) FREE(tok2)free((char*)(tok2)); |
112 | break; |
113 | |
114 | case M_OP_DF9: |
115 | |
116 | |
117 | if( (hv = GET_MACRO(tok1)Get_name(tok1, Macs, 0)) != NIL(HASH)((HASH*)((void*)0)) && !(hv->ht_flag & M_INIT0x0200) ) |
118 | break; |
119 | |
120 | |
121 | case M_OP_EQ1: |
122 | Def_macro( tok1, tok2, flag ); |
123 | break; |
124 | |
125 | case M_OP_DFCL11: |
126 | |
127 | |
128 | if( (hv = GET_MACRO(tok1)Get_name(tok1, Macs, 0)) != NIL(HASH)((HASH*)((void*)0)) && !(hv->ht_flag & M_INIT0x0200) ) |
129 | break; |
130 | |
131 | |
132 | case M_OP_CL3: |
133 | tok2 = Expand( tok2 ); |
134 | Def_macro( tok1, tok2, M_EXPANDED0x0008 | flag ); |
135 | FREE( tok2 )free((char*)(tok2)); |
136 | break; |
137 | |
138 | case M_OP_CM17:{ |
139 | CELLPTR cp; |
140 | STRINGPTR sp; |
141 | |
142 | if (flag & M_PUSH0x0100) { |
| |
143 | Error("Nested conditional definition [%s ?= %s] ignored", |
144 | tok1, tok2); |
145 | } |
146 | else { |
147 | cp = Def_cell(tok1); |
148 | if (cp->ce_flag & F_MULTI0x0002) { |
| |
149 | LINKPTR lp; |
150 | for(lp=cp->ce_prq; lp->cl_next; lp=lp->cl_next); |
151 | cp = lp->cl_prq; |
152 | } |
153 | TALLOC(sp,1,STRING)if ((sp = (STRING*) calloc((unsigned int)(1), (size_t)sizeof( STRING))) == (STRING*)0) {No_ram();}; |
| 9 | | Within the expansion of the macro 'TALLOC':
| |
b | Assuming pointer value is null |
|
154 | sp->st_string = DmStrDup(tok2); |
| 10 | | Access to field 'st_string' results in a dereference of a null pointer (loaded from variable 'sp') |
|
155 | sp->st_next = cp->ce_cond; |
156 | cp->ce_cond = sp; |
157 | |
158 | tok1 = NIL(char)((char*)((void*)0)); |
159 | } |
160 | } |
161 | break; |
162 | } |
163 | |
164 | if (tok1) { |
165 | if ( LastMacName != NIL(char)((char*)((void*)0)) ) |
166 | FREE( LastMacName )free((char*)(LastMacName)); |
167 | |
168 | LastMacName = tok1; |
169 | } |
170 | |
171 | DB_RETURN( 1 )return (1); |
172 | } |
173 | |
174 | |
175 | |
176 | PUBLIC int |
177 | Macro_op( op ) |
178 | |
179 | |
180 | char *op; |
181 | { |
182 | int ret = 0; |
183 | DB_ENTER( "macro_op" ); |
184 | |
185 | if ( *op == '!' ) { |
186 | ret = M_OP_SI32; |
187 | op++; |
188 | } |
189 | |
190 | switch( *op ) { |
191 | case '=': ret |= M_OP_EQ1; break; |
192 | case ':': ret |= M_OP_CL3; op++; break; |
193 | |
194 | case '+': |
195 | op++; |
196 | if( *op == ':' ) { |
197 | ret |= M_OP_PLCL7; |
198 | op++; |
199 | } |
200 | else { |
201 | ret |= M_OP_PL5; |
202 | } |
203 | break; |
204 | |
205 | case '*': |
206 | op++; |
207 | if( *op == ':' ) { |
208 | ret |= M_OP_DFCL11; |
209 | op++; |
210 | } |
211 | else { |
212 | ret |= M_OP_DF9; |
213 | } |
214 | break; |
215 | |
216 | case '?': |
217 | ret |= M_OP_CM17; |
218 | op++; |
219 | break; |
220 | } |
221 | |
222 | if( *op != '=' ) |
223 | ret = 0; |
224 | else { |
225 | op++; |
226 | |
227 | if( *op != '\0' ) |
228 | ret = 0; |
229 | } |
230 | |
231 | DB_RETURN( ret )return (ret); |
232 | } |