Loading...
Searching...
No Matches
line.f90
Go to the documentation of this file.
1!> @file
2!! @defgroup group_line Line
3!! Standard `#line` directive support for the fpx Fortran preprocessor
4!!
5!! This module implements full support for the ISO C99/C11 `#line` directive,
6!! which is also widely used in Fortran preprocessors.
7!!
8!! The `#line` directive allows changing the logical line number and/or source
9!! filename reported by the preprocessor. It is particularly useful for:
10!! - Code generators
11!! - Literate programming tools
12!! - Macro-heavy generated code
13!! - Accurate `__LINE__` and `__FILE__` expansion in included/generated files
14!!
15!! Supported forms (standard compliant):
16!! - `#line <number>`
17!! - `#line <number> "<filename>"`
18!!
19!! When a `#line` directive is encountered, the current context (line number and
20!! filename) is updated immediately. This affects all subsequent diagnostics,
21!! `__LINE__`, `__FILE__`, and `__FILENAME__` macros.
22!!
23!! <h2 class="groupheader">Examples</h2>
24!!
25!! 1. Basic line number reset:
26!! @code{.f90}
27!! #line 100
28!! print *, "This line will be reported as line 100"
29!! @endcode
30!!
31!! 2. Changing both line number and filename (common in generated code):
32!! @code{.f90}
33!! #line 42 "generated_code.f90"
34!! integer :: x = 1 ! This will appear as line 42 in generated_code.f90
35!! @endcode
36!!
37!! @par Remarks
38!! - The line number in `#line N` refers to the **next** line after the directive.
39!! - Filename must be quoted if provided.
40!! - Invalid line numbers or malformed directives emit a warning but are ignored.
41!! - Updates the shared `context` object used by the logging and macro systems.
42module fpx_line
43 use fpx_path
44 use fpx_logging
45 use fpx_context
46
47 implicit none; private
48
49contains
50
51 !> Handle the standard #line directive
52 !! Supports two standard forms:
53 !! #line <number>
54 !! #line <number> "<filename>"
55 !!
56 !! This updates the current line number (`ctx%line`) and optionally the current
57 !! filename (`ctx%path`) for subsequent diagnostics, `__LINE__`, and `__FILE__`
58 !! expansions.
59 !!
60 !! Fully compliant with ISO C99 / C11 �6.10.4 and common Fortran preprocessor behavior.
61 !!
62 !! @param[inout] ctx Context source line containing the #line directive
63 !! @param[in] token Usually 'DEFINE' � keyword matched in lowercase
64 !!
65 !! @b Remarks
66 !! @ingroup group_line
67 subroutine handle_line(ctx, token)
68 type(context), intent(inout) :: ctx
69 character(*), intent(in) :: token
70 !private
71 character(:), allocatable :: temp, num_str, fname
72 integer :: pos, iostat, new_line
73 logical :: has_filename
74
75 ! Skip #line keyword
76 pos = index(lowercase(ctx%content), token) + len(token)
77 temp = trim(adjustl(ctx%content(pos:)))
78
79 if (len_trim(temp) == 0) then
80 call printf(render(diagnostic_report(level_warning, &
81 message='Synthax error', &
82 label=label_type('#line directive with no arguments', index(token, lowercase(ctx%content)) + len(token) + 1, 1), &
83 source=ctx%path), &
84 trim(ctx%content), ctx%line))
85 return
86 end if
87
88 ! Extract line number
89 pos = index(temp, ' ')
90 if (pos > 0) then
91 num_str = temp(:pos-1)
92 fname = trim(adjustl(temp(pos:)))
93 has_filename = .true.
94 else
95 num_str = trim(temp)
96 has_filename = .false.
97 end if
98
99 ! Parse line number
100 read(num_str, *, iostat=iostat) new_line
101 if (iostat /= 0 .or. new_line < 1) then
102 call printf(render(diagnostic_report(level_warning, &
103 message='Synthax error', &
104 label=label_type('Invalid line number in #line directive', index(token, lowercase(ctx%content)) + len(token) + 1, len(num_str)), &
105 source=ctx%path), &
106 trim(ctx%content), ctx%line))
107 end if
108
109 ! Update current line number (subtract 1 because the next line will be +1)
110 ctx%line = new_line - 1
111
112 ! Update filename if provided (strip quotes)
113 if (has_filename) then
114 if (fname(1:1) == '"' .and. len(fname) > 1) then
115 fname = fname(2:index(fname(2:), '"'))
116 end if
117 if (len_trim(fname) > 0) then
118 ctx%path = trim(fname)
119 end if
120 end if
121 end subroutine
122end module
subroutine handle_line(ctx, token)
Handle the standard line directive Supports two standard forms: line <number> line <number> "<filenam...
Definition line.f90:68
Interface to render diagnostic messages and labels.
Definition logging.f90:185
Source location and content snapshot for precise diagnostics Instances of this type are created for e...
Definition context.f90:99
Definition of diagnostic message.
Definition logging.f90:269
Represents text as a sequence of ASCII code units. The derived type wraps an allocatable character ar...
Definition logging.f90:246