/*
* DESCRIPTION
* Main file for the keyvalue assignment. See assignment specs.
*/
#include <errno.h>
#include <libgen.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include "auxdefs.h"
#include "listmap.h"
static char *exec_name = NULL;
static int exit_status = EXIT_SUCCESS;
static char *stdin_filename = "-";
void eprintf (char *format, ...) {
va_list args;
xfflush (NULL);
va_start (args, format);
xvfprintf (stderr, format, args);
va_end (args);
xfflush (NULL);
exit_status = EXIT_FAILURE;
}
char *trim (char *string){
int i;
unsigned int length = strlen(string);//start from end of string
length = length -1;//length starts at n-1
for(;;){
if(string[length]== ' '){ /*looks at the characters at the end and keeps
*going back. If its a space makes string point
*to null character and decrements the length.*/
string[length] = '\0';
if(length == 0){ /*if the string is empty return NULL*/
return NULL;
}
length --;
}else break;
};
for(i = 0;i < strlen(string); i++){/*starts from the beginning of the string
*till the end of it which is length.
*goes through the string till it hits a non
*whitespace character then returns the address
*of it*/
if(string[i] != ' '){
return &string[i];
}
};
return NULL; /*should the empty string not be caught return NULL*/
}
void printpairs(listmap_ref map, char *string){
listmap_itor_ref itor = new_listmap_itor (map); /*itor goes through the map and while there are things to go
*through it will print out the keys and associated values.
*then go to the next pair.
*after it is finished then itor is freed*/
while (hascurr_listmap_itor (itor)) {
char *value = get_value_listmap_itor (itor); /*stores value does not throw it away*/
/*if string is passed as NULL then print all keys values if not then only print the ones that have the same
* values as string*/
if(string == NULL || strcmp(value, string)==0){
xprintf ("%s = %s\n", get_key_listmap_itor (itor), value);
}
next_listmap_itor (itor);
}
free_listmap_itor (itor);
}
/*this function just prints out the key and associated value if value is equal to NULL
* then an error message is printed */
void print_key(char *key,char * value){
if(value == NULL){ /*if key is not found then
*will print out an error message*/
xprintf("%s: key not found\n", key);
}else{
xprintf("%s = %s \n", key, value); /*else prints out the key and its
*value */
}
}
void scanline(char *line, listmap_ref map){
char *equals = strchr(line, '='); /*if the line is just a key then get
*the associated value and print out
*the key and value*/
line = trim(line); /*trims the line if the line has
*nothing or starts with a hash makr
*ignores it as a comment*/
if(strlen(line)==0 || line[0]== '#'){ /*line[0] beginning of string*/
return;
}
else if(equals == NULL){
char *val = get_listmap(map, line);
print_key(line, val);
}
else if(line[0] == '='){ /*if line starts with an equal sign*/
if(strlen(line)==1){ /*if the equal sign is the only character*/
printpairs(map, NULL); /*call the function print pairs and print out
*all of the pairs, if pass null print all
*if not NULL then print out only pairs with
*the same value*/
}else{
char *new = line +1; /*takes of the equal sign*/
new = trim(new); /*trims the whitespace off the string*/
printpairs(map, new);
}
}else{
if(line[strlen(line) - 1] == '='){
char* oldval;
line[strlen(line) - 1] = '\0'; /*delete the associated key*/
line = trim(line); /* trims any whitespace before equal sign*/
oldval = put_listmap(map, line, NULL);
print_key(line, oldval);
if(oldval != NULL){
free(oldval);
}
}else{
char* value = equals +1; /*it is a key definition*/
char *oldvalue;
*equals = '\0';
line=trim(line);
value=trim(value);
oldvalue = put_listmap(map, line, value);
print_key(line, oldvalue);
if(oldvalue != NULL){
free(oldvalue);
}
}
}
}
void scanfile (FILE *infile, char *filename, listmap_ref map, bool eflag) {
int linenr;
for (linenr = 1;; ++linenr) {
char buffer[1024];
char *charptr = fgets (buffer, sizeof buffer, infile);
if (charptr == NULL) break;
charptr = strchr (buffer, '\n');
if (charptr != NULL) {
*charptr = '\0';
}else {
eprintf ("%s: %s: line %d: missing newline\n",
exec_name, filename, linenr);
continue;
}
if(eflag){
xprintf ("%s: %d: %s\n", filename, linenr, buffer);
}
scanline(buffer, map);
}
}
int main (int argc, char **argv) {
bool eflag = FALSE;//-e option
listmap_ref map = NULL;
exec_name = basename (argv[0]);
map = new_listmap ();
opterr = FALSE;
for(;;){
int option = getopt(argc, argv, "e");
if(option == EOF)break;
switch(option){
case 'e': eflag = TRUE; break;
default : eprintf("%s: -%c: invalid option\n", exec_name, optopt);
exit_status = EXIT_FAILURE;
};
};
if (argc < 2) {
scanfile (stdin, stdin_filename, map, eflag);
}else {
int argi;
for (argi = 1; argi < argc; ++argi) {
if (strcmp (argv[argi], stdin_filename) == 0) {
scanfile (stdin, stdin_filename, map, eflag);
}else {
char *filename = argv[argi];
FILE *infile = fopen (filename, "r");
if (infile == NULL) {
eprintf ("%s: %s: %s\n",
exec_name, filename, strerror (errno));
}else {
scanfile (infile, filename, map, eflag);
xfclose (infile);
}
};
};
};
free_listmap(map);
return exit_status;
}
RCSC(KEYVALUE_C,"$Id: keyvalue.c,v 1.1 2007-05-27 21:04:59-07 - - $")