#include #include #include #include #include #include /* Error constants */ enum { UNKNOWN_FAIL = 1, MALLOC_FAIL, NEEDARG_FAIL, FOPEN_FAIL, WRITE_FAIL, TIME_FAIL, MISC_FAIL }; /* Standard data identifiers for nodes */ enum { CHAR = 1, INT, LONG, DOUBLE, CHARP, INTP, LONGP, DOUBLEP, NODEP }; /* node - node type suitable for being a member in a linked list. */ /* name - the name of the data in this node */ /* data - pointer to arbitrary data */ /* type - implementation-defined identifier for what kind of data this node holds */ typedef struct LNODE { struct LNODE *previous; char *name; void *data; int type; struct LNODE *next; } node; /* Condition should be one of the above enum'd strings. Info is optional; it can just be NULL when irrelevant. */ void throw(long unsigned int condition, void *info) { switch(condition) { case UNKNOWN_FAIL: printf("unknown failure\n"); exit(UNKNOWN_FAIL); case MALLOC_FAIL: printf("malloc failure\n"); exit(MALLOC_FAIL); case NEEDARG_FAIL: printf("usage: %s\n", (char *) info); exit(NEEDARG_FAIL); case FOPEN_FAIL: printf("failed to open: %s\n", (char *) info); exit(FOPEN_FAIL); case WRITE_FAIL: printf("failed to write: %s\n", (char *) info); exit(WRITE_FAIL); case TIME_FAIL: printf("time error: %s\n", (char *) info); exit(TIME_FAIL); case MISC_FAIL: printf("%s\n", (char *) info); exit(MISC_FAIL); default: printf("You shouldn't be seeing this.\nSomething is very wrong.\n"); exit(-256); } } /* arrccat -- function to copy arr2len bytes from arr2 to the arr1len'th position of arr1. returns *newarr, and stores the length */ /* of newarr[] in arr1len (that's why it needs to be a pointer to arr1len and not just a long unsigned integer). */ char *arrccat(char *arr1, char *arr2, size_t *arr1len, size_t arr2len) { char *newarr; unsigned int i, i2; newarr = malloc(*arr1len+arr2len); i = i2 = 0; for(i = 0; i < *arr1len; i++) { newarr[i] = arr1[i]; } for(i2 = 0; i2 < arr2len; i2++, i++) { newarr[i] = arr2[i2]; } *arr1len = *arr1len+arr2len; return newarr; } /* mastrcat -- improved string concat function. returns a pointer to the first element in a buffer containing the strings str1 */ /* and str2 joined end-to-end. */ char *mastrcat(char *str1, char *str2) { unsigned long int nbi, stri, nbsize; char *nbuf; nbi = stri = 0; nbsize = (strlen(str1) + strlen(str2)); nbuf = malloc(nbsize); for(stri = 0; str1[stri] != '\0'; nbi++, stri++) { nbuf[nbi] = str1[stri]; } for(stri = 0; str2[stri] != '\0'; nbi++, stri++) { nbuf[nbi] = str2[stri]; } return nbuf; } /* open stdin if path is null */ FILE *file_open(char *path, char *mode) { FILE *fd; fd = 0; if(!mode) { return(NULL); } if(path == NULL || !strcmp(path, "-")) { fd = fopen("/dev/stdin", mode); } else { fd = fopen(path, mode); } if(!fd) { return(NULL); } return(fd); } /* return a buffer containing the contents of fd, or NULL if failure. Store the size of the new buffer in newsize; -1 on fail. */ char *file_read(FILE *fd, int *newsize) { int bufsize, c, i; char *buf, *tmpbuf; /* bufsize is arbitrary */ bufsize = 4096; c = i = 0; buf = tmpbuf = 0; if( !(buf = malloc(bufsize))) { *newsize = -1; return(NULL); } for(i = 0; (c = fgetc(fd)) != EOF; i++) { if(i >= bufsize) { if( !(tmpbuf = malloc(bufsize *= 2))) { *newsize = -1; return(NULL); } memcpy(tmpbuf, buf, i-1); free(buf); buf = tmpbuf; } buf[i] = c; } *newsize = i; return(buf); } node *node_create() { node *newnode; newnode = 0; ; return(newnode); } int node_free(node *todel) { node *nodep; nodep = todel->previous; nodep->next = todel->next; free(todel->name); free(todel->data); free(todel); return(0); } /* concat - return a buffer of size new_size containing s1 and s2 concatenated. */ char *concat(char *a1, char *a2, int a1_size, int a2_size) { char *newbuf; newbuf = 0; if( !(newbuf = malloc(a1_size+a2_size))) { throw(MALLOC_FAIL, "concat: couldn't create buffer"); } if(a1_size) { memcpy(newbuf, a1, a1_size); } if(a2_size) { memcpy((newbuf + a1_size), a2, a2_size); } return(newbuf); }