115 implicit none;
private
151 type(
context),
intent(in) :: ctx
152 type(
macro),
allocatable,
intent(inout) :: macros(:)
153 character(*),
intent(in) :: token
155 character(:),
allocatable :: val, name, temp
156 integer :: pos, paren_start, paren_end, i, npar, imacro, level
159 temp =
trim(adjustl(ctx%content(pos + 1:)))
161 paren_start =
index(temp,
'(')
162 pos =
index(temp,
' ')
163 if (pos > 0 .and. pos < paren_start) paren_start = 0
165 if (paren_start > 0)
then
166 name =
trim(temp(:paren_start - 1))
168 if (
global%undef .contains. name)
return
169 paren_end = 0; level = 0
171 select case (temp(i:i))
182 if (paren_end == 0)
then
184 message=
'Syntax error', &
185 label=
label_type(
'Missing closing parenthesis in macro definition',
len_trim(ctx%content) + 1, 1), &
187 trim(ctx%content), ctx%line))
190 val =
trim(adjustl(temp(paren_end + 1:)))
191 temp = temp(paren_start + 1:paren_end - 1)
195 if (temp(pos:pos) ==
',')
then
200 if (
len_trim(temp) > 0) npar = npar + 1
202 if (.not.
allocated(macros))
allocate(macros(0))
204 if (name ==
'defined')
then
206 message=
'Reserved macro name', &
207 label=
label_type(
'"defined" cannot be used as a macro name', paren_start + 1,
len(name)), &
209 trim(ctx%content), ctx%line))
212 if (.not.
is_defined(name, macros, imacro))
then
213 call add(macros, name, val)
216 macros(imacro) =
macro(name, val)
219 if (
index(temp,
'...') > 0)
then
220 macros(imacro)%is_variadic = .true.
222 if (
allocated(macros(imacro)%params))
deallocate(macros(imacro)%params)
223 allocate(macros(imacro)%params(npar))
226 do while (pos <=
len_trim(temp) .and. i <= npar)
227 do while (pos <=
len_trim(temp) .and. temp(pos:pos) ==
' ')
232 do while (pos <=
len_trim(temp) .and. temp(pos:pos) /=
',')
235 macros(imacro)%params(i) = temp(paren_start:pos - 1)
240 macros(imacro)%is_variadic = .false.
241 if (
allocated(macros(imacro)%params))
deallocate(macros(imacro)%params)
242 allocate(macros(imacro)%params(npar))
245 do while (pos <=
len_trim(temp) .and. i <= npar)
246 do while (pos <=
len_trim(temp) .and. temp(pos:pos) ==
' ')
251 do while (pos <=
len_trim(temp) .and. temp(pos:pos) /=
',' .and. temp(pos:pos) /=
' ')
255 macros(imacro)%params(i) = temp(paren_start:pos - 1)
258 if (temp(pos:pos) ==
',') pos = pos + 1
263 pos =
index(temp,
' ')
265 name =
trim(temp(:pos - 1))
266 val =
trim(adjustl(temp(pos + 1:)))
272 if (
global%undef .contains. name)
return
273 if (.not.
allocated(macros))
allocate(macros(0))
274 if (.not.
is_defined(name, macros, imacro))
then
275 call add(macros, name, val)
278 macros(imacro) =
macro(name, val)
298 type(
context),
intent(in) :: ctx
299 type(
macro),
allocatable,
intent(inout) :: macros(:)
300 character(*),
intent(in) :: token
302 character(:),
allocatable :: name
307 name =
trim(adjustl(ctx%content(pos:)))
309 if (macros(i) == name)
then
317 message=
'Unknown macro', &
subroutine, public handle_undef(ctx, macros, token)
Process a #undef directive.
subroutine, public handle_define(ctx, macros, token)
Process a #define directive.
type(global_settings), public global
Global preprocessor configuration instance.
logical function, public is_defined(name, macros, idx)
Determine whether a macro is currently defined.
pure character(len_trim(str)) function, public lowercase(str)
Convert string to lower case (respects contents of quotes).
Generic renderer for diagnostics and source excerpts.
Append macros to a macro table.
Remove a macro definition from a table.
Return the number of stored macro definitions.
Locate the position of a substring.
Return the trimmed length of a string object.
Return the length of a string object.
Remove trailing blanks from a string object.
Snapshot of a source location within the preprocessing stream.
Structured compiler diagnostic.
Diagnostic label identifying a region of source text.
Representation of a preprocessor macro.