Coverage Report

Created: 2026-07-30 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmllpkgc/llpkgc_frag.c
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.
2
   See accompanying file LICENSE.rst for details.  */
3
4
#include <stdint.h>
5
#include <stdlib.h>
6
#include <string.h>
7
8
#include "llpkgc_frag.h"
9
10
#define CALLBACK_MAYBE(PARSER, NAME)                                           \
11
0
  do {                                                                         \
12
0
    const llpkgc_frag_settings_t* settings;                                    \
13
0
    settings =                                                                 \
14
0
        (const llpkgc_frag_settings_t*) (PARSER)->llpkgc_frag__settings;       \
15
0
    if(settings == NULL || settings->NAME == NULL) {                           \
16
0
      err = 0;                                                                 \
17
0
      break;                                                                   \
18
0
    }                                                                          \
19
0
    err = settings->NAME((PARSER));                                            \
20
0
  } while(0)
21
22
#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN)                          \
23
0
  do {                                                                         \
24
0
    const llpkgc_frag_settings_t* settings;                                    \
25
0
    settings =                                                                 \
26
0
        (const llpkgc_frag_settings_t*) (PARSER)->llpkgc_frag__settings;       \
27
0
    if(settings == NULL || settings->NAME == NULL) {                           \
28
0
      err = 0;                                                                 \
29
0
      break;                                                                   \
30
0
    }                                                                          \
31
0
    err = settings->NAME((PARSER), (START), (LEN));                            \
32
0
    if(err == -1) {                                                            \
33
0
      err = PFFE_USER;                                                         \
34
0
      llpkgc_frag_set_error_reason((PARSER), "Span callback error in " #NAME); \
35
0
    }                                                                          \
36
0
  } while(0)
37
38
enum llpkgc_frag_state {
39
  PFFS_START = 0,
40
  PFFS_UNQUOTED = 1,
41
  PFFS_DOUBLE_QUOTED = 2,
42
  PFFS_SINGLE_QUOTED = 3,
43
};
44
45
void llpkgc_frag_init(llpkgc_frag_t* parser,
46
0
    const llpkgc_frag_settings_t* settings) {
47
0
  llpkgc_frag__internal_init(parser);
48
0
  parser->llpkgc_frag__settings = (void*) settings;
49
0
}
50
51
0
void llpkgc_frag_reset(llpkgc_frag_t* parser) {
52
0
  llpkgc_frag_settings_t* settings = parser->llpkgc_frag__settings;
53
0
  void* data = parser->data;
54
0
  llpkgc_frag__internal_init(parser);
55
0
  parser->llpkgc_frag__settings = settings;
56
0
  parser->data = data;
57
0
}
58
59
0
void llpkgc_frag_settings_init(llpkgc_frag_settings_t* settings) {
60
0
  memset(settings, 0, sizeof(*settings));
61
0
}
62
63
llpkgc_frag_errno_t llpkgc_frag_execute(llpkgc_frag_t* parser, const char* data,
64
0
    size_t len) {
65
0
  return llpkgc_frag__internal_execute(parser, data, data + len);
66
0
}
67
68
0
llpkgc_frag_errno_t llpkgc_frag_finish(llpkgc_frag_t* parser) {
69
0
  int err = PFFE_OK;
70
71
0
  if(parser->error == PFFE_LOOKAHEAD) {
72
0
    if(parser->error_pos == NULL) {
73
0
      parser->error = PFFE_INTERNAL;
74
0
      parser->reason = "Missing lookahead error position";
75
0
      return parser->error;
76
0
    }
77
78
0
    parser->llpkgc_frag__eof = 1;
79
0
    llpkgc_frag_resume(parser);
80
0
    err = llpkgc_frag_execute(parser, parser->error_pos, 1);
81
0
    parser->llpkgc_frag__eof = 0;
82
83
0
    if(err != PFFE_OK) {
84
0
      return err;
85
0
    }
86
87
0
    parser->llpkgc_frag__lookahead = 0;
88
0
  } else if(parser->error != 0) {
89
0
    return parser->error;
90
0
  }
91
92
0
  switch(parser->llpkgc_frag__state) {
93
0
    case PFFS_UNQUOTED:
94
0
      CALLBACK_MAYBE(parser, on_frag_complete);
95
0
      if(err != PFFE_OK) {
96
0
        parser->error = err;
97
0
        return err;
98
0
      }
99
0
      break;
100
101
0
    case PFFS_DOUBLE_QUOTED:
102
0
    case PFFS_SINGLE_QUOTED:
103
0
      parser->reason = "Unterminated quote at end of input";
104
0
      parser->error = PFFE_UNFINISHED;
105
0
      return PFFE_UNFINISHED;
106
107
0
    case PFFS_START:
108
0
      break;
109
0
  }
110
111
0
  CALLBACK_MAYBE(parser, on_fraglist_complete);
112
0
  if(err != PFFE_OK) {
113
0
    parser->error = err;
114
0
    return err;
115
0
  }
116
117
0
  return PFFE_OK;
118
0
}
119
120
0
void llpkgc_frag_pause(llpkgc_frag_t* parser) {
121
0
  if(parser->error != PFFE_OK) {
122
0
    return;
123
0
  }
124
0
  parser->error = PFFE_PAUSED;
125
0
  parser->reason = "Paused";
126
0
}
127
128
0
void llpkgc_frag_resume(llpkgc_frag_t* parser) {
129
0
  if(parser->error != PFFE_PAUSED && parser->error != PFFE_LOOKAHEAD) {
130
0
    return;
131
0
  }
132
0
  parser->error = 0;
133
0
}
134
135
0
llpkgc_frag_errno_t llpkgc_frag_get_errno(const llpkgc_frag_t* parser) {
136
0
  return parser->error;
137
0
}
138
139
0
const char* llpkgc_frag_get_error_reason(const llpkgc_frag_t* parser) {
140
0
  return parser->reason;
141
0
}
142
143
0
void llpkgc_frag_set_error_reason(llpkgc_frag_t* parser, const char* reason) {
144
0
  parser->reason = reason;
145
0
}
146
147
0
const char* llpkgc_frag_get_error_pos(const llpkgc_frag_t* parser) {
148
0
  return parser->error_pos;
149
0
}
150
151
0
const char* llpkgc_frag_errno_name(llpkgc_frag_errno_t err) {
152
0
  switch(err) {
153
0
    case PFFE_OK:
154
0
      return "PFFE_OK";
155
0
    case PFFE_INTERNAL:
156
0
      return "PFFE_INTERNAL";
157
0
    case PFFE_PAUSED:
158
0
      return "PFFE_PAUSED";
159
0
    case PFFE_USER:
160
0
      return "PFFE_USER";
161
0
    case PFFE_UNFINISHED:
162
0
      return "PFFE_UNFINISHED";
163
0
    case PFFE_LOOKAHEAD:
164
0
      return "PFFE_LOOKAHEAD";
165
0
  }
166
0
  return "INVALID_ERRNO";
167
0
}
168
169
int llpkgc_frag__lookahead_dq_backslash(llpkgc_frag_t* s, const char* p,
170
0
    const char* endp) {
171
0
  if(p == endp) {
172
0
    llpkgc_frag_set_error_reason(s, "Invalid lookahead state");
173
0
    return PFFE_INTERNAL;
174
0
  }
175
176
0
  if(p + 1 == endp) {
177
0
    if(s->llpkgc_frag__eof != 0) {
178
0
      s->llpkgc_frag__lookahead = 0;
179
0
      return 1;
180
0
    }
181
0
    s->llpkgc_frag__lookahead = (uint8_t) *p;
182
0
    return PFFE_LOOKAHEAD;
183
0
  }
184
185
0
  s->llpkgc_frag__lookahead = 0;
186
187
0
  if(*p != '\\') {
188
0
    llpkgc_frag_set_error_reason(s, "Invalid lookahead state");
189
0
    return PFFE_INTERNAL;
190
0
  }
191
192
0
  switch(p[1]) {
193
0
    case '$':
194
0
    case '`':
195
0
    case '"':
196
0
    case '\\':
197
0
      return 0;
198
0
    default:
199
0
      return 1;
200
0
  }
201
0
}
202
203
int llpkgc_frag__fragment_text(llpkgc_frag_t* s, const char* p,
204
0
    const char* endp) {
205
0
  int err;
206
0
  SPAN_CALLBACK_MAYBE(s, on_fragment_text, p, endp - p);
207
0
  return err;
208
0
}
209
210
int llpkgc_frag__frag_complete(llpkgc_frag_t* s, const char* p,
211
0
    const char* endp) {
212
0
  int err;
213
  CALLBACK_MAYBE(s, on_frag_complete);
214
0
  return err;
215
0
}