/* parse.c -- Hui Dai September 2003 for cs170 */ #include #include "parse.h" int isspecial(char c) /* returns true if c is one of the four special chars*/ { return (c == '<' || c == '>' || c == '&' || c == '|'); } int parse(CMD ** head) { int num_token; /* number of distinct pieces in the input */ int i, j, k, w; /* general counters */ char tmp[LINEMAX+1]; /* stores a space and cmd ln input */ char * buff = tmp + 1; /* where cmd ln input actually starts */ char parsedLine[PARSEDLINE]; /* stores the properly spaced input tokens */ char * tokenPtr[LINEMAX]; /* stores list of ptrs into buf2 */ CMD *first, *curr, *next; /* pointer holders */ tmp[0] = ' '; *head = NULL; if(fgets(buff, LINEMAX, stdin) == NULL) /* most likely CTRL-D */ { return EOF_REACHED; } /* correctly spaces the tokens within parsedLine[] */ for(num_token = i = j = 0; i < strlen(buff); ++i) /* offset within buff */ { /* offset in parsedLine */ if(isspace(buff[i])) continue; /* checks for boundary conditions which imply a new token is found */ if(isspace(buff[i-1]) || (isspecial(buff[i-1]) && !isspecial(buff[i])) || (!isspecial(buff[i-1]) && isspecial(buff[i])) ) tokenPtr[num_token++] = parsedLine + j; parsedLine[j++] = buff[i]; /* checks if current token ends */ if( isspace(buff[i+1]) || (isspecial(buff[i]) && !isspecial(buff[i+1])) || (!isspecial(buff[i]) && isspecial(buff[i+1])) ) parsedLine[j++] = '\0'; } if(num_token == 0) return EMPTYLINE; parsedLine[j] = '\0'; /* checks for syntactical mistakes */ for(i = 0; i < num_token; ++i) { if(isspecial(*tokenPtr[i])) { /* not single special char and not ">>" */ if(*(tokenPtr[i]+1) != '\0' && strcmp(tokenPtr[i], ">>") != 0) { return BADSYMBOL; } /* in order: special char as first token || special char as last, but it is not & */ /* || & is not the last token */ /* || two special char in a row */ if(i == 0 || (i == num_token-1 && *(tokenPtr[i]) != '&') || (*(tokenPtr[i]) == '&' && i != num_token-1) || isspecial(*tokenPtr[i-1]) ) { return BADPLACEMENT; } } } if ( (*head = first = curr = (CMD *) malloc(sizeof(CMD))) == NULL) { return MALLOCFAILED; } first->background = *(tokenPtr[num_token-1]) == '&' ? --num_token : 0; first->prevCmd = NULL; for(i = 0; i < num_token; i += (j+1)) { curr->in_redir = NULL; curr->out_redir = NULL; for(j = 0; i+j < num_token; ++j) if( *(tokenPtr[i+j]) == '|') break; for(k = i+j-2; k > i; --k) if( *(tokenPtr[k]) == '<') { if( (curr->in_redir = (char *) strdup(tokenPtr[k+1])) == NULL) return MALLOCFAILED; break; } for(k = i+j-2; k > i; --k) if( *(tokenPtr[k]) == '>') { curr->appending = (*(tokenPtr[k]+1) == '>' ? 1 : 0 ); if( (curr->out_redir = (char *) strdup(tokenPtr[k+1])) == NULL) return MALLOCFAILED; break; } for(k = i+1, w = j; k < i+j; ++k) if( isspecial(*(tokenPtr[k]))) w -= 2; if( (curr->argv = (char **) malloc( sizeof(char *) * (w + 1))) == NULL) return MALLOCFAILED; if( (curr->argv[0] = (char *) strdup(tokenPtr[i])) == NULL) return MALLOCFAILED; curr->file = curr->argv[0]; curr->argv[w] = NULL; for(k = i+1, w = 1; k < i+j; ++k) { if (isspecial(*(tokenPtr[k]))) { ++k; continue; } if( (curr->argv[w++] = (char *) strdup(tokenPtr[k])) == NULL) return MALLOCFAILED; } if(i+j < num_token) { if( (next = (CMD *) malloc(sizeof(CMD))) == NULL) return MALLOCFAILED; curr->nextCmd = next; next->prevCmd = curr; curr = next; } else curr->nextCmd = NULL; } return SUCCESS; } int cmd_free(CMD * cmd) { int i; CMD *curr, *next; if( (curr = cmd) == NULL) { return 1; } do { if(curr->in_redir != NULL) free(curr->in_redir); if(curr->out_redir != NULL) free(curr->out_redir); if(curr->argv != NULL) { for(i = 0; (curr->argv)[i] != NULL; ++i) free((curr->argv)[i]); free(curr->argv); } next = curr->nextCmd; free(curr); curr = next; }while(curr != NULL); return 0; }