#ident "$URL: svn://elmer/devel/SVN/SDDAS/trunk/libant/StrHier.c $ %D% SwRI" /* StrHier.c -- build and manipulate hierachical lists of strings */ #include /* for FILE i/o */ #include /* for strchr,etc. */ #include /* for strchr,etc. */ #include "ant.h" /* for LinkList,StrHier,etc. */ #include "Destroy.h" /* for LinkList,StrHier,etc. */ #define MAXSTR 80 /* longest text line */ /* DestroyStrHier */ void DestroyStrHier(void *V) { int i; DestroyObj_t *D, *Dnext; StrHier S = (StrHier)V; D = S->Destroy; for (i=D->NToFree-1; i>=0; i--) { if (S[i].Destroy) free((char*)S[i].Destroy); free(S[i].str); if (S[i].info) { if (((VoidFree_t *)S[i].info)->Destroy) { Dnext = ((VoidFree_t *)S[i].info)->Destroy; (Dnext->Free)(S[i].info); } } } free((char*)S); } /* IndentOf -- returns # of columns (tabs=8) before first char */ int IndentOf(char *str) { #define SPACE ' ' #define TAB '\t' int columns; /* how many columns of leading whitespace */ char *s; /* used to traverse string */ if (str == NULL) return 0; for (columns=0,s=str; *s == TAB || *s == SPACE; s++) columns += (*s == TAB) ? 8 : 1; return columns; } /* StrHierAddChildPair -- add string and associated number */ StrHier StrHierAddChildPair(StrHier parent,char *str,int n) { StrHierNode *node; /* new node for string hierarchy */ parent->sublist = LinkAppend(parent->sublist, node = StrHierNodeCreate(str)); node->parent = parent; SNUM(node) = n; return node; } /* StrHierAssignStr -- assign a string to a StrHier node */ void StrHierAssignStr(StrHierNode *node,char *str) { node->str = strdup(str); } /* StrHierDepth -- returns depth of StrHier node */ int StrHierDepth( StrHier h) { int depth=0; StrHier parent=StrHierParent(h); for (; parent; parent=StrHierParent(parent)) ++depth; return depth; } /* StrHierFetch -- fetch a string hierachy from a file */ StrHier StrHierFetch(char *TreeFile) { FILE *fp; char line[MAXSTR]; char *name; StrHier tree; if ((fp = fopen(TreeFile,"r")) == NULL) return NULL; tree = StrHierNodeCreate((name = strchr(TreeFile,'.')) ? ++name : TreeFile); StrHierParse(fp,line,tree,-1); return tree; } /* StrHierName -- returns name for a string hierarchy */ char * StrHierNamer(char *label,StrHier hier) { strcpy(label,hier->str); return label; } /* StrHierNodeCreate -- create node with string and sublist */ StrHier StrHierNodeCreate(char *str) { StrHierNode *node; /* create new node with its own copy of string */ node = (StrHierNode *)calloc(1,sizeof(StrHierNode)); node->str = (char *)calloc(strlen(str)+1,sizeof(char)); strcpy(node->str,str); node->Destroy = (DestroyObj_t *)calloc(1, sizeof(DestroyObj_t)); node->Destroy->NToFree = 1; node->Destroy->Free = DestroyStrHier; return node; } /* StrHierCreateNodes -- create n number of nodes with string and sublist */ StrHier StrHierCreateNodes(int n) { StrHierNode *nodes; if(n <= 0) { fprintf(stderr,"ERROR: Input to StrHierCreateNodes is %d\n",n); return (StrHier)0; } /* create new node with its own copy of string */ nodes = (StrHierNode *)calloc(n, sizeof(StrHierNode)); nodes->Destroy = (DestroyObj_t *)calloc(1, sizeof(DestroyObj_t)); nodes->Destroy->NToFree = n; nodes->Destroy->Free = DestroyStrHier; return nodes; } /* StrHierParse -- create string hierarchy by parsing file add lines with same indent to parents sublist create subhier for lines with more indentation return first less indented line */ char * StrHierParse(FILE *fp,char *line,StrHier parent,int PrevIndent) { StrHierNode *node; /* new node for string hierarchy */ int ThisIndent; /* how much this line is indented */ line = mfgets(line,MAXSTR,fp); while (line && (ThisIndent=IndentOf(line)) > PrevIndent) { node = StrHierNodeCreate(PastWhite(line)); parent->sublist = LinkAppend(parent->sublist,(void *)node); line = StrHierParse(fp,line,node,ThisIndent); } return line; } /* StrHierPrint -- print the string hierarchy */ void StrHierPrint(StrHier hier) { LinkList list; int depth = StrHierDepth(hier); /* indent 3 spaces per level */ while (depth--) printf(" "); /* print node */ printf("%s\n",hier->str); /* print children */ for (list = hier->sublist; list; list = list->next) StrHierPrint((StrHier)LinkData(list)); }