static int mnt_table_parse_next(struct libmnt_parser *pa,
				struct libmnt_table *tb,
				struct libmnt_fs *fs)
{
	char *s;
	int rc;

	assert(tb);
	assert(pa);
	assert(fs);

	/* read the next non-blank non-comment line */
next_line:
	do {
		if (getline(&pa->buf, &pa->bufsiz, pa->f) < 0)
			return -EINVAL;
		pa->line++;
		s = strchr(pa->buf, '\n');
		if (!s) {
			DBG(TAB, ul_debugobj(tb, "%s:%zu: no final newline",
						pa->filename, pa->line));

			/* Missing final newline?  Otherwise an extremely */
			/* long line - assume file was corrupted */
			if (feof(pa->f))
				s = memchr(pa->buf, '\0', pa->bufsiz);

		/* comments parser */
		} else if (tb->comms
		    && (tb->fmt == MNT_FMT_GUESS || tb->fmt == MNT_FMT_FSTAB)
		    && is_comment_line(pa->buf)) {
			do {
				rc = append_comment(tb, fs, pa->buf, feof(pa->f));
				if (!rc)
					rc = next_comment_line(pa, &s);
			} while (rc == 0);

			if (rc == 1 && feof(pa->f))
				rc = append_comment(tb, fs, NULL, 1);
			if (rc < 0)
				return rc;

		}

		if (!s)
			goto err;
		*s = '\0';
		if (s > pa->buf && *(s - 1)  == '\r')
			*(--s) = '\0';
		s = (char *) skip_blank(pa->buf);
	} while (*s == '\0' || *s == '#');

	if (tb->fmt == MNT_FMT_GUESS) {
		tb->fmt = guess_table_format(s);
		if (tb->fmt == MNT_FMT_SWAPS)
			goto next_line;			/* skip swap header */
	}

	switch (tb->fmt) {
	case MNT_FMT_FSTAB:
		rc = mnt_parse_table_line(fs, s);
		break;
	case MNT_FMT_MOUNTINFO:
		rc = mnt_parse_mountinfo_line(fs, s);
		break;
	case MNT_FMT_UTAB:
		rc = mnt_parse_utab_line(fs, s);
		break;
	case MNT_FMT_SWAPS:
		if (strncmp(s, "Filename\t", 9) == 0)
			goto next_line;			/* skip swap header */
		rc = mnt_parse_swaps_line(fs, s);
		break;
	default:
		rc = -1;	/* unknown format */
		break;
	}

	if (rc == 0)
		return 0;
err:
	DBG(TAB, ul_debugobj(tb, "%s:%zu: %s parse error", pa->filename, pa->line,
				tb->fmt == MNT_FMT_MOUNTINFO ? "mountinfo" :
				tb->fmt == MNT_FMT_SWAPS ? "swaps" :
				tb->fmt == MNT_FMT_FSTAB ? "tab" : "utab"));

	/* by default all errors are recoverable, otherwise behavior depends on
	 * the errcb() function. See mnt_table_set_parser_errcb().
	 */
	return tb->errcb ? tb->errcb(tb, pa->filename, pa->line) : 1;
}
static int mnt_table_parse_next(struct libmnt_parser *pa,
				struct libmnt_table *tb,
				struct libmnt_fs *fs)
{
	char *s;
	int rc;

	assert(tb);
	assert(pa);
	assert(fs);

	 
next_line:
	do {
		if (getline(&pa->buf, &pa->bufsiz, pa->f) < 0)
			return -EINVAL;
		pa->line++;
		s = strchr(pa->buf, '\n');
		if (!s) {
			DBG(TAB, ul_debugobj(tb, "%s:%zu: no final newline",
						pa->filename, pa->line));

			 
			 
			if (feof(pa->f))
				s = memchr(pa->buf, '\0', pa->bufsiz);

		 
		} else if (tb->comms
		    && (tb->fmt == MNT_FMT_GUESS || tb->fmt == MNT_FMT_FSTAB)
		    && is_comment_line(pa->buf)) {
			do {
				rc = append_comment(tb, fs, pa->buf, feof(pa->f));
				if (!rc)
					rc = next_comment_line(pa, &s);
			} while (rc == 0);

			if (rc == 1 && feof(pa->f))
				rc = append_comment(tb, fs, NULL, 1);
			if (rc < 0)
				return rc;

		}

		if (!s)
			goto err;
		*s = '\0';
		if (s > pa->buf && *(s - 1)  == '\r')
			*(--s) = '\0';
		s = (char *) skip_blank(pa->buf);
	} while (*s == '\0' || *s == '#');

	if (tb->fmt == MNT_FMT_GUESS) {
		tb->fmt = guess_table_format(s);
		if (tb->fmt == MNT_FMT_SWAPS)
			goto next_line;			 
	}

	switch (tb->fmt) {
	case MNT_FMT_FSTAB:
		rc = mnt_parse_table_line(fs, s);
		break;
	case MNT_FMT_MOUNTINFO:
		rc = mnt_parse_mountinfo_line(fs, s);
		break;
	case MNT_FMT_UTAB:
		rc = mnt_parse_utab_line(fs, s);
		break;
	case MNT_FMT_SWAPS:
		if (strncmp(s, "Filename\t", 9) == 0)
			goto next_line;			 
		rc = mnt_parse_swaps_line(fs, s);
		break;
	default:
		rc = -1;	 
		break;
	}

	if (rc == 0)
		return 0;
err:
	DBG(TAB, ul_debugobj(tb, "%s:%zu: %s parse error", pa->filename, pa->line,
				tb->fmt == MNT_FMT_MOUNTINFO ? "mountinfo" :
				tb->fmt == MNT_FMT_SWAPS ? "swaps" :
				tb->fmt == MNT_FMT_FSTAB ? "tab" : "utab"));

	 
	return tb->errcb ? tb->errcb(tb, pa->filename, pa->line) : 1;
}