Skip to content

Commit dca914c

Browse files
committed
Make relative $INCLUDE relative to includer
1 parent 0671a08 commit dca914c

File tree

1 file changed

+54
-10
lines changed

1 file changed

+54
-10
lines changed

src/zone.c

+54-10
Original file line numberDiff line numberDiff line change
@@ -143,29 +143,67 @@ nonnull_all
143143
static int32_t open_file(
144144
parser_t *parser, zone_file_t *file, const char *path, size_t length)
145145
{
146+
char *abs = NULL;
147+
146148
(void)parser;
147149

148150
if (!(file->name = strndup(path, length)))
149151
return ZONE_OUT_OF_MEMORY;
150152

153+
const char *rel = file->name;
154+
151155
#if _WIN32
152156
char buf[1];
153-
DWORD size = GetFullPathName(file->name, sizeof(buf), buf, NULL);
157+
// relative include paths are relative to including file
158+
if (file != &parser->first && PathIsRelative(path)) {
159+
assert(parser->file->path != not_a_file);
160+
assert(parser->file->handle != NULL);
161+
const char *dir = parser->file->path;
162+
int dirlen = 0;
163+
for (int i = 0; i < INT32_MAX && dir[i]; i++) {
164+
if (dir[i] == '/' || dir[i] == '\\')
165+
dirlen = i + 1;
166+
}
167+
int len;
168+
len = snprintf(buf, sizeof(buf), "%.*s\\%s", dirlen, dir, file->name);
169+
assert(len != -1);
170+
if (!(abs = malloc(len + 1)))
171+
return ZONE_READ_ERROR;
172+
(void)snprintf(abs, len + 1, "%.*s\\%s", dirlen, dir, file->name);
173+
rel = abs;
174+
}
175+
DWORD size = GetFullPathName(rel, sizeof(buf), buf, NULL);
154176
if (!size)
155-
return ZONE_READ_ERROR;
177+
goto read_error;
156178
if (!(file->path = malloc(size)))
157-
return ZONE_OUT_OF_MEMORY;
158-
if (!(length = GetFullPathName(file->name, size, file->path, NULL)))
159-
return ZONE_READ_ERROR;
160-
if (length != size - 1)
161-
return ZONE_READ_ERROR;
179+
goto out_of_memory;
180+
(void)GetFullPathName(rel, size, file->path, NULL);
162181
#else
163182
char buf[PATH_MAX];
164-
if (!realpath(file->name, buf))
165-
return ZONE_READ_ERROR;
183+
if (file != &parser->first && path[0] != '/') {
184+
assert(parser->file->path != not_a_file);
185+
assert(parser->file->handle != NULL);
186+
const char *dir = parser->file->path;
187+
int dirlen = 0;
188+
for (int i = 0; i < INT32_MAX && dir[i]; i++) {
189+
if (dir[i] == '/')
190+
dirlen = i + 1;
191+
}
192+
int len;
193+
len = snprintf(buf, sizeof(buf), "%.*s/%s", dirlen, dir, file->name);
194+
if (!(abs = malloc((size_t)len + 1)))
195+
return ZONE_OUT_OF_MEMORY;
196+
(void)snprintf(abs, (size_t)len + 1, "%.*s/%s", dirlen, dir, file->name);
197+
rel = abs;
198+
}
199+
if (!realpath(rel, buf))
200+
goto read_error;
166201
if (!(file->path = strdup(buf)))
167-
return ZONE_OUT_OF_MEMORY;
202+
goto out_of_memory;
168203
#endif
204+
if (abs)
205+
free(abs);
206+
abs = NULL;
169207

170208
if (!(file->handle = fopen(file->path, "rb")))
171209
switch (errno) {
@@ -192,6 +230,12 @@ static int32_t open_file(
192230
file->lines.head = file->lines.tape;
193231
file->lines.tail = file->lines.tape;
194232
return 0;
233+
read_error:
234+
if (abs) free(abs);
235+
return ZONE_READ_ERROR;
236+
out_of_memory:
237+
if (abs) free(abs);
238+
return ZONE_OUT_OF_MEMORY;
195239
}
196240

197241
diagnostic_pop()

0 commit comments

Comments
 (0)