Last active
June 8, 2020 20:17
-
-
Save tonyhutter/135155fc185f568d61c046875d39699c to your computer and use it in GitHub Desktop.
parsing manifest lines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <ctype.h> | |
/* | |
* Parse a line from the manifest in the form of: | |
* | |
* <src path> <whitespace separator> <dest path> | |
* | |
* If the paths have spaces, they must be quoted. | |
* | |
* On success, return 0 along with allocated src and dest strings. These | |
* must be freed when you're finished with them. On failure return non-zero, | |
* and set src and dest to NULL. | |
* | |
* Note, leading and tailing whitespace are ok. They just get ignored. | |
* Lines with only whitespace are ignored. A line of all whitespace will | |
* return 0, with src and dest being NULL, so users should not check for | |
* 'if (*src == NULL)' to see if the function failed. They should be looking | |
* at the return code. | |
*/ | |
int | |
unifyfs_parse_manifest_line(char *line, char **src, char **dest) | |
{ | |
char *new_src = NULL, *new_dest = NULL; | |
char *copy, *tmp; | |
unsigned long copy_len; | |
int i; | |
unsigned int tmp_count; | |
int in_quotes = 0; | |
int rc = 0; | |
copy = strdup(line); | |
copy_len = strlen(copy) + 1; /* +1 for '\0' */ | |
/* Replace quotes and separator with '\0' */ | |
for (i = 0; i < copy_len; i++) { | |
if (copy[i] == '"') { | |
in_quotes ^= 1; /* toggle */ | |
copy[i] = '\0'; | |
} else if (isspace(copy[i]) && !in_quotes) { | |
/* | |
* Allow any whitespace for our separator | |
*/ | |
copy[i] = '\0'; | |
} | |
} | |
/* | |
* copy[] now contains a series of strings, one after the other | |
* (possibly containing some NULL strings, which we ignore) | |
*/ | |
tmp = copy; | |
while (tmp < copy + copy_len) { | |
tmp_count = strlen(tmp); | |
if (tmp_count > 0) { | |
/* We have a real string */ | |
if (!new_src) { | |
new_src = strdup(tmp); | |
} else { | |
if (!new_dest) { | |
new_dest = strdup(tmp); | |
} else { | |
/* Error: a third file name */ | |
rc = 1; | |
break; | |
} | |
} | |
} | |
tmp += tmp_count + 1; | |
} | |
/* Some kind of error parsing a line */ | |
if (rc != 0 || (new_src && !new_dest)) { | |
free(new_src); | |
free(new_dest); | |
new_src = NULL; | |
new_dest = NULL; | |
if (rc == 0) { | |
rc = 1; | |
} | |
} | |
*src = new_src; | |
*dest = new_dest; | |
free(copy); | |
return rc; | |
} | |
int main(void) | |
{ | |
FILE * fp; | |
char * line = NULL; | |
size_t len = 0; | |
ssize_t read; | |
char *src, *dest; | |
int rc; | |
fp = fopen("manifest", "r"); | |
if (fp == NULL) | |
exit(EXIT_FAILURE); | |
while ((read = getline(&line, &len, fp)) != -1) { | |
/* Get rid of trailing newline */ | |
*strchr(line, '\n') = '\0'; | |
rc = unifyfs_parse_manifest_line(line, &src, &dest); | |
printf("%s:\n %s\n %s\n rc = %d\n\n", line, src, dest, | |
rc); | |
} | |
fclose(fp); | |
if (line) | |
free(line); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment