Search code examples
c

Modeling nested lists in C


Problem

I am implementing a basic shell in C and am confused on how to best represent a list of commands where each command might be multiple commands that are run in parallel. For example, parsing the below batch file:

ls -l directory
cat README.md & du -sh directory
exit

would produce a data structure like such:

[
  [
    ["ls", "-l", "directory"],
  ],
  [
    ["cat", "README.md"],
    ["du", "-sh", "directory"],
  ],
  [
    ["exit"],
  ],
]

In particular, I am struggling to determine the most convenient data structure(s) to use as arguments to my exec_many function.

int exec_many(/* list of list of list of strings /*) {
    ...
}

I am willing to implement a subset of vector if that is necessary, but I assume there is a more C-like way to go about this problem.

What I've Tried

The only solution I've been able to come up with that meets the requirements is an API like such:

struct Command {
    string *args;
    int argc;
};

struct Commands {
    Command *commands;
    int count;
};

int exec_many(Commands *commands, int count) {
    ...
}

My issues with this solution are:

  1. Defining a struct for each nested layer seems tedious and unnecessary
  2. Constructing the structures requires full knowledge of length beforehand

Solution

  • The structure you have come up with looks fine.

    Defining a struct for each nested layer seems tedious and unnecessary

    Einstein is often quoted as having said: Make everything as simple as possible, but not simpler1. The complexity of a solution to a problem generally has to match the complexity of the problem it solves.

    The problem you are trying to model involves a tree of entities; therefore, the solution must involve representing a tree of entities.

    As a matter of fact, if the solution did not involve a tree, then I would frown.

    Constructing the structures requires full knowledge of length beforehand

    I would suggest that it is fine that it requires full knowledge of length beforehand, but if you really do not want that, then things will get significantly more complicated: what you actually need is a tree which consists of linked lists.

    With a linked list, you can keep adding nodes until you have no more nodes to add. When processing the list, you keep processing nodes until there are no more nodes.


    1 Einstein did not say exactly that; he said a more convoluted thing, which can be summarized, and generalized, by paraphrasing it like that. The summarized phrase has come to be known as Einstein's Razor. See Wikiquote: Albert Einstein, see Wikipedia: Philosophical razor, and see Quote investigator: Everything Should Be Made as Simple as Possible, But Not Simpler