/**************************************************************/ /* */ /* UNIX 1 / WS 92/93 Gruppe ux803 */ /* 3. Uebung - Aufgabe 2 - parser.c */ /* */ /* Vorname Name Matrikelnr. */ /* --------- ------- ------------- */ /* Dietmar Dierks 125761 */ /* Roman Czyborra 127221 */ /* Torsten Buller 117894 */ /* Gerasimos Paliatsaras 140956 */ /* */ /**************************************************************/ #include #include "parser.h" /* clean-up routine: * ----------------- */ void forget (cmd) struct kommando *cmd; { static char **p; if (!cmd) return; if (cmd -> num_tok1) { for (p = cmd -> token_1; *p; ++ p) free (*p); free (cmd -> token_1); } if (cmd -> num_tok2) { for (p = cmd -> token_2; *p; ++ p) free (*p); free (cmd -> token_2); } if (cmd -> inp_tok) free (cmd -> inp_tok); if (cmd -> out_tok) free (cmd -> out_tok); if (cmd -> next) forget (cmd -> next); cfree (cmd); } /* variables made global for auxiliary routines: * --------------------------------------------- */ static char *toread, /* points to the next char to read in *buf */ ***tok; /* points to the currently built token vector */ int *num; /* points to length of *tok */ /* auxiliary routines: * ------------------- */ static int isblank (c) char c; { return (strchr(" \t\v\f\r\n", c)); } static int isfunc (c) char c; { return (strchr ("<>|&;", c)); } static int istok (c) char c; { return (! strchr(" <>|&;\t\v\f\r\n",c)); } static int blktok () { static char chr; while ((chr = *toread) && isblank (chr)) ++ toread; return (chr && ! isfunc (chr)); } /* blktok () skips blanks and looks for a token * its return value says if there is a character * after some or no blanks that is not a func */ static char *token() { static char chr, *ptr; int len; ptr = toread; for (len = 0; (chr = * ptr++) && istok (chr); ++len); ptr = (char *) malloc ((len + 1) * sizeof (char)); if (ptr) { strncpy (ptr, toread, len); toread += len; ptr [len] = '\0'; } return ptr; }/* token() duplicates one token into the heap * toread must point to a real token whenever token() is called */ static struct kommando * new () { static struct kommando * n; n = (struct kommando *) calloc (1, sizeof (struct kommando)); if (n) num = & n->num_tok1, tok = & n->token_1; return n; } /* new() generates and initializes a new struct kommando */ static int invalid0c(s) struct kommando *s; { if (s->num_tok1) return (s->is_pipe && !s->num_tok2); else return (s->is_pipe || s->inp_tok || s->out_tok); } /* checks, if *s is an invalid null command */ /* main routine: * ============= */ struct kommando * parseline (buf) char *buf; { static char chr, * error, AMBINP [] = "ambiguous input redirection", AMBOUT [] = "ambiguous output redirection", MISINP [] = "missing name for input", MISOUT [] = "missing name for output", MULPIP [] = "can't handle multiple pipe", NULCOM [] = "invalid null command", MALERR [] = "out of memory"; static struct kommando *result, *cmd; error = NULL; result = cmd = new (); if (!cmd) error = MALERR; toread = buf; while (!error && (chr = *toread)) if (istok (chr)) { if (*num) *tok = (char **) realloc (*tok, (*num + 2) * sizeof (char *)); else *tok = (char **) malloc (2 * sizeof (char *)); if (*tok) (*tok) [*num] = token (), (*tok) [++*num] = NULL; else error = MALERR; } else { ++ toread; switch (chr) { case '<': if (cmd->inp_tok || cmd->is_pipe) error = AMBINP; else if (!blktok ()) error = MISINP; else cmd->inp_tok = token (); break; case '>': if (cmd->out_tok) error = AMBOUT; else if (!blktok ()) error = MISOUT; else cmd->out_tok = token (); break; case '|': if (cmd->is_pipe++) error = MULPIP; else if (cmd->out_tok) error = AMBOUT; else if (!*num) error = NULCOM; else num = & cmd->num_tok2, tok = & cmd->token_2; break; case '&': cmd -> is_ampersand = 1; /* flow through */ case ';': if (invalid0c (cmd)) error = NULCOM; else { cmd = cmd -> next = new (); if (! cmd) error = MALERR; } } } if (!error && invalid0c (cmd)) error = NULCOM; if (error) { fprintf (stderr, "%s\n", error); forget(result); return NULL; } else return result; }