If you’re using the macros from <sys/queue.h> to implement a circular doubly linked list (TAILQ), the inversion issue occurs because you’re using LIST_INSERT_HEAD, which inserts at the head of the list. Instead, to maintain the original order (FIFO), you should use TAILQ_INSERT_TAIL.

Here’s how you can create a circular doubly linked list and add lines to it while preserving their order:

Steps:

  1. Include the necessary header: Use <sys/queue.h>.
  2. Define a struct for the list entry: Each entry holds a line of text and pointers for the circular doubly linked list.
  3. Initialize the list: Use TAILQ_HEAD and TAILQ_INIT.
  4. Insert lines: Use TAILQ_INSERT_TAIL to add lines at the end.

Example Code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>

#define LINE_MAX 128

// Define the structure for each list entry
struct Line {
    char text[LINE_MAX];           // Holds the line text
    TAILQ_ENTRY(Line) entries;     // Macro for pointers
};

// Define the head of the list
TAILQ_HEAD(LineList, Line);

int main() {
    struct LineList list;          // Declare the list
    struct Line *line;             // Temporary pointer for a line
    char buffer[LINE_MAX];         // Buffer to hold input lines

    // Initialize the list
    TAILQ_INIT(&list);

    // Example: Adding lines to the list
    printf("Enter lines of text (empty line to finish):\n");
    while (fgets(buffer, LINE_MAX, stdin) != NULL) {
        // Remove the newline character
        size_t len = strlen(buffer);
        if (len > 0 && buffer[len - 1] == '\n') {
            buffer[len - 1] = '\0';
        }

        // Stop if the input is empty
        if (strlen(buffer) == 0) {
            break;
        }

        // Allocate memory for a new line
        line = malloc(sizeof(struct Line));
        if (line == NULL) {
            perror("malloc failed");
            exit(EXIT_FAILURE);
        }

        // Copy the text into the line structure
        strncpy(line->text, buffer, LINE_MAX);

        // Insert the line at the tail of the list
        TAILQ_INSERT_TAIL(&list, line, entries);
    }

    // Print all lines in the list
    printf("\nLines in the list:\n");
    TAILQ_FOREACH(line, &list, entries) {
        printf("%s\n", line->text);
    }

    // Free memory and clear the list
    while ((line = TAILQ_FIRST(&list)) != NULL) {
        TAILQ_REMOVE(&list, line, entries);
        free(line);
    }

    return 0;
}

Explanation:

  1. Circular Doubly Linked List:
  • The TAILQ macros create a circular doubly linked list.
  • TAILQ_INSERT_TAIL ensures lines are appended at the end, preserving their order (FIFO).
  1. Key Macros:
  • TAILQ_INIT(&list): Initializes the list.
  • TAILQ_INSERT_TAIL(&list, line, entries): Inserts a new entry at the tail.
  • TAILQ_REMOVE(&list, line, entries): Removes an entry from the list.
  • TAILQ_FOREACH(line, &list, entries): Iterates over the list.
  1. Buffer Handling:
  • The buffer size is 128 characters, matching the problem’s requirements.
  • Newline characters are removed for clean output.

Output Example:

Input:

Hello, World!
This is a test.
Another line.
<empty line>

Output:

Lines in the list:
Hello, World!
This is a test.
Another line.

This approach maintains the original input order (FIFO) without inversion.