Skip to content

Instantly share code, notes, and snippets.

@tonyhutter
Last active June 8, 2020 20:17
Show Gist options
  • Save tonyhutter/135155fc185f568d61c046875d39699c to your computer and use it in GitHub Desktop.
Save tonyhutter/135155fc185f568d61c046875d39699c to your computer and use it in GitHub Desktop.
parsing manifest lines
#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