Commits

Anonymous committed 4d6bc5a

تغييرات كثيرة + عنصر نلي لscta

Comments (0)

Files changed (27)

 test: scta.* test.c
-	gcc -o test -std=c99 -pedantic -g -Wall scta.c test.c
+	gcc -o test -std=c99 -pedantic -g -Wall -Wextra scta.c test.c
 
 memcheck: test
 	valgrind --tool=memcheck ./test
     +------------------+
     |     ELEMENT_N    |
     +------------------+
+    |         0        |  Auto-null terminated
+    +------------------+
     |      STORAGE     |  (same size as normal array elements)
     +------------------+
     
     return (RET); \
 }
 
+#define ___INTERNAL_INT_ARRAY_PRINTER___\
+    fprintf(stderr, "length: %d, size: %zu, { ", SCTA__INTERN_LEN(ra)[0], SCTA__INTERN_SIZE(ra)[0]);\
+    for (int i = 0; i < SCTA__INTERN_LEN(ra)[0]+2; ++i) fprintf(stderr, "%d ", ((int *)((char *) ra + SCTA_HEAD))[i]);\
+    fprintf(stderr, "} \n");
 
 
 // XXX EXTERN SHOULD NOT APPEAR IN THIS DOCUMENT
     if (length == INT_MAX) 
         ERRMSG_AND_RETURN(false, "cannot increase array size do to int limit.")
         
-    if (!(temp=realloc(*ra, (SCTA_HEAD)+ size*length + size*count + size))) 
-        ERRMSG_AND_RETURN(false, "memory operation failed: new size is %zu", ((SCTA_HEAD+size)+size*length+size))
+    if (!(temp=realloc(*ra, (SCTA_HEAD)+ size*length + size*count + size + size))) 
+        ERRMSG_AND_RETURN(false, "memory operation failed: new size is %zu", ((SCTA_HEAD+size)+size*length+size+size))
     *ra = temp;
     
     
     memmove( ((char *) *ra) + SCTA_HEAD + at*size + size*count, 
              ((char *) *ra) + SCTA_HEAD + at*size, 
-             (length*size) - (at*size) + size);
+             (length*size) - (at*size) + size + size);
     
     
     SCTA__INTERN_LEN(*ra)[0]+=count;
     if (!length) 
         ERRMSG_AND_RETURN(false, "cannot shorten a zero length array")
         
-    if (at < length-1) {
-        memmove( ((char *) *ra) + SCTA_HEAD + at*size, 
-                 ((char *) *ra) + SCTA_HEAD + at*size + size*count, 
-                 (length*size) - (at*size + size*count) + size );
-    }
     
-    if (!(temp=realloc(*ra, SCTA_HEAD + size*length - size*count + size))) 
+    memmove( ((char *) *ra) + SCTA_HEAD + at*size, 
+             ((char *) *ra) + SCTA_HEAD + at*size + size*count, 
+             (length*size) - (at*size + size*count) + size + size);
+    
+    if (!(temp=realloc(*ra, SCTA_HEAD + size*length - size*count + size + size))) 
         ERRMSG_AND_RETURN(false, "memory operation failed: new size is %zu", ((SCTA_HEAD+size)+size*length-size))
     *ra = temp;
     
     if (!size) 
         ERRMSG_AND_RETURN(NULL, "requested array member size is 0. minimum is 1.")
     
-    if (!(ra = malloc(SCTA_HEAD + size)))
+    if (!(ra = malloc(SCTA_HEAD + size + size)))
         ERRMSG_AND_RETURN(NULL, "could not allocate enough memory: requested %zu", SCTA_HEAD + size)
         
-    memset(ra, 0, SCTA_HEAD + size);
+    memset(ra, 0, SCTA_HEAD + size + size);
     
     /* debugging macros
     fprintf(stderr, "base %p\n", c);
 bool scta_macro_set_length_(char **z, int newl){
     void *ra = *z-SCTA_HEAD;
     int oldl = SCTA__INTERN_LEN(ra)[0];
-    
+    int size = SCTA__INTERN_SIZE(ra)[0];
     if (newl > oldl) {
         if (!make_space(&ra, oldl, newl-oldl)) return false;
-        memset((char *)ra+SCTA_HEAD+(oldl*SCTA__INTERN_SIZE(ra)[0]), 0, (newl-oldl)*SCTA__INTERN_SIZE(ra)[0]);
+        memset((char *)ra+SCTA_HEAD+(oldl*SCTA__INTERN_SIZE(ra)[0]), 0, (newl-oldl)*size + size + size);
     }
     if (newl < oldl) {
         if (!collapse_space(&ra, newl, oldl-newl)) return false;
     if (!make_space(&ra, at, 1)) return false;
     
     memmove(    ((char *) ra) + SCTA_HEAD + size*at, 
-                ((char *) ra) + SCTA_HEAD + size*(SCTA__INTERN_LEN(ra)[0]) , size);
+                SCTA__INTERN_STORAGE(ra), size);
     
+    
+    /*REMMOVE LATER */ memset((char *) ra + SCTA_HEAD + size * SCTA__INTERN_LEN(ra)[0], 0, size);
     *z = (char *) ra + SCTA_HEAD;
     return true;
 }
     memmove(    ((char *) ra) + SCTA_HEAD + size*at, 
                 target_addr , size*target_length);
     
-    *z = (char *) ra + SCTA_HEAD;
     
+    /*REMMOVE LATER */ memset((char *) ra + SCTA_HEAD + size * SCTA__INTERN_LEN(ra)[0], 0, size);
+    *z = (char *) ra + SCTA_HEAD;
     return true;
 }
 
                                  "\tand spans %d element(s)\n", oldl, at, target_length)
 
     
-    memmove( ((char *) ra) + SCTA_HEAD + size*oldl, 
-             ((char *) ra) + SCTA_HEAD + size*at, size);
+    memmove( SCTA__INTERN_STORAGE(ra), 
+            ((char *) ra) + SCTA_HEAD + size*at, size);
     
     if (!collapse_space(&ra, at, target_length)) return false;
     
+    /*REMMOVE LATER */ memset((char *) ra + SCTA_HEAD + size * SCTA__INTERN_LEN(ra)[0], 0, size);
     *z = (char *) ra + SCTA_HEAD;
-    
     return true;
 }
 
 #define SCTA___PTR2(PTR, OFFSET)  ((void **)  (((char *) PTR) + SCTA__OFFSET_PTR2   + OFFSET))
 
 
+
 // returns the size, length, and status of the true bigening of the array (internal)
 #define SCTA__INTERN_SIZE(X) SCTA___SIZE(X, 0)
 #define SCTA__INTERN_LEN(X)  SCTA___LEN(X, 0)
 #define SCTA__INTERN_PTR2(X) SCTA___PTR2(X, 0)
 
 
+
+
 // returns the size, length, and status of apparent bigening of the array (external)
 #define SCTA__EXTERN_SIZE(X) SCTA___SIZE(X, -SCTA_HEAD)
 #define SCTA__EXTERN_LEN(X)  SCTA___LEN(X,  -SCTA_HEAD)
 #define SCTA__EXTERN_PTR1(X) SCTA___PTR1(X, -SCTA_HEAD)
 #define SCTA__EXTERN_PTR2(X) SCTA___PTR2(X, -SCTA_HEAD)
 
-extern FILE *scta_config_debug;
-extern int scta_config_version[3];
+#define SCTA__INTERN_STORAGE(X) (((char *) X)+SCTA__OFFSET_HEADER+(SCTA__INTERN_SIZE(X)[0]*SCTA__INTERN_LEN(X)[0]+SCTA__INTERN_SIZE(X)[0]))
+#define SCTA__EXTERN_STORAGE(X) ((X)+(SCTA__EXTERN_SIZE(X)[0]*SCTA__EXTERN_LEN(X)[0]+SCTA__EXTERN_SIZE(X)[0]))
+
 
 void* scta_macro_new_(size_t size);
 void scta_macro_free_(void *c);
 */
 
 
+extern FILE *scta_config_debug;
+extern int scta_config_version[3];
 
 
+#define scta_new(type)                              (scta_macro_new_(sizeof(type)))/*
+sctman:scta_new
 
+NAME
+    scta_new
 
-#define scta_new(type)                              (scta_macro_new_(sizeof(type)))/*
+SYNOPSIS
+    bool scta_new(type)
+    
+DESCRIPTION
+    Takes any type as its input, and returns a pointer to a zero length array
+    with elements of the same type.
 
-DESCRIPTION    
-    Takes any variable type as its input.
+NOTES
+    This function is implemented as a macro.
 
 RETURN
     a pointer of type `type *' on success, and null otherwise.
 */
 
 
-#define scta_free(A)                                (scta_macro_free_(A))/*
+#define scta_free                                scta_macro_free_/*
+sctman:scta_free
+NAME
+    scta_free
+    
+SYNOPSIS
+    void scta_free(array)
 
 DESCRIPTION    
     Takes a dynamic array and frees it.
 
+RETURN
+    None
 */
 
+
 #define scta_length(A)                              (SCTA__EXTERN_LEN(A)[0])/*
 
-DESCRIPTION    
-    This macro returns the length of `A'
+sctman:scta_length
+NAME
+    scta_length
     
+SYNOPSIS
+    int scta_length(array)
+
+DESCRIPTION    
+    Returns the length of the array 
+
 RETURN
-    an integer of type `int'
-    
+    The length of `array' as an int.
 */
 
 #define scta_set_length(A, newl)                    (scta_macro_set_length_((char **) &(A), newl))/*
 */
 
 #define scta_insert(A, where, what)                 ((SCTA__EXTERN_INT1(A)[0]=where),\
-                                                     ((A)[*SCTA__EXTERN_LEN(A)]=what),\
+                                                     ((A)[scta_length(A)+1]=what),\
                                                      scta_macro_insert_((char **) &(A)))/*
                                                      
 DESCRIPTION    
                                                      scta_macro_delete_subset_((char **) &(A)))
 
 #define scta_pop(A, var)                            (scta_delete_subset((A), INT_MAX, 1) ?\
-                                                     ((var)=((A)[scta_length(A)]),true) :\
+                                                     ((var)=((A)[scta_length(A)+1]),true) :\
                                                      false)
 
 #define scta_subset(array, at, length)              (scta_macro_subset_(sizeof((array[0])), (at), (length), (array)))
 
 #include "scta.h"
 
-int main (int argc, char **argv){
+int main (){
     
     scta_config_debug=stderr;
     {// push tests
         {// insert size size(int) 
             int *a = scta_new(int);
             
-            for (int i = 0; i < 10; ++i) {
-                assert(scta_length(a) == i);
+            for (int i = 1; i < 11; ++i) {
+                assert(scta_length(a) == i-1);
                 assert(scta_push(a, i*2));
             }
-            for (int i = 0; i < 10; ++i) assert(a[i] == i*2);
+            assert(a[0] == 2);
+            assert(a[1] == 4);
+            assert(a[2] == 6);
+            assert(a[3] == 8);
+            assert(a[4] == 10);
+            assert(a[5] == 12);
+            assert(a[6] == 14);
+            assert(a[7] == 16);
+            assert(a[8] == 18);
+            assert(a[9] == 20);
             
             scta_free(a);    
         }
         int pv = 0;
         
         assert(scta_pop(a, pv));
-        assert(pv == 60);
         assert(scta_length(a) == 5);
+        assert(pv == 60);
         
         assert(scta_pop(a, pv));
         assert(pv == 50);
         assert(scta_set_length(z, 20000));
         
         for (int i = 0; i < 20000; ++i) z[i] = i*i;
-        for (int i = 0; i < 20000; ++i) assert(z[i] == i*i);
+        for (int i = 0; i < 20000; ++i) assert(z[i] == (uint64_t) i*i);
         assert(scta_set_length(z, 10000));
         assert(scta_set_length(z, 20000));
-        for (int i = 0; i < 10000; ++i) assert(z[i] == i*i);
+        for (int i = 0; i < 10000; ++i) assert(z[i] == (uint64_t) i*i);
         for (int i = 10000; i < 20000; ++i) assert(z[i] == 0);
         
         scta_free(z);
+test: sctac.* test.c
+	gcc -o test -std=c99 -pedantic -g -Wall -Wextra -I../a ../a/scta.c sctac.c test.c
+
+memcheck: test
+	valgrind --tool=memcheck ./test
+
+clean:
+	rm test
+#include "scta.h"
+#include "string.h"
+
+FILE *sctac_config_debug = NULL;
+int sctac_config_version[3] = {1, 0, 0};
+
+char *sctac_insert_(char **string, char *appendee, int at){
+    char *s = *string;
+    int len = strlen(appendee);
+    
+    if (!scta_insert_array(s, at, appendee, len)) {
+        return NULL;
+    }
+    
+    *string = s;
+    return s;
+}
+
+char *sctac_append_(char **string, char *appendee){
+    return sctac_insert_(string, appendee, scta_length(*string));
+}
+
+
+char *sctac_delete_(char **string, int start, int length){
+    char *s = *string;
+    
+    if (!scta_delete_subset (s, start, length)) {
+        return NULL;
+    }
+    
+    *string = s;
+    return s;
+}
+
+
+char *sctac_clone_(char **string, int start, int length){
+    char *s = *string;
+    
+    if (!scta_subset (s, start, length)) {
+        return NULL;
+    }
+    
+    *string = s;
+    return s;
+}
+
+
+#ifndef SCTAC_H
+#define SCTAC_H
+
+extern FILE *sctac_config_debug;
+extern int sctac_config_version[3];
+
+
+char *sctac_insert_(char **string, char *appendee, int at);
+char *sctac_append_(char **string, char *appendee);
+char *sctac_delete_(char **string, int start, int length);
+char *sctac_clone_(char **string, int start, int length);
+
+#define sctac_insert(S, A, T) sctac_insert_(&(S), (A), (T))
+#define sctac_append(S, A) sctac_append_(&(S), (A))
+#define sctac_delete(S, B, L) sctac_delete_(&(S), (B), (L))
+#define sctac_clone(S, B, L) sctac_clone_(&(S), (B), (L))
+
+
+
+#endif
Binary file added.
+#include <stdio.h>
+#include "scta.h"
+#include "sctac.h"
+
+int main(){
+    char *s;
+    
+    s = scta_new(char);
+    puts(s);
+    sctac_append(s, "hello their my friend!");
+    puts(s);
+    sctac_insert(s, "epic ", -7);
+    puts(s);
+    sctac_delete(s, 1, 7);
+    puts(s);
+    sctac_delete(s, 0, 5);
+    puts(s);
+    
+    scta_free(s);
+    
+    return 0;
+    
+}
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
+
 #include "sctframe.h"
 #include "scta.h"
 
         // bad memory
         return NULL;
     }
-    f->addresses = scta_new(void *);
-    if (!f->addresses) {
+    f->records = scta_new(struct record);
+    if (!f->records) {
         // darray fail
+        free(f);
         return NULL;
     } 
     return f;
 }
 
 
-#if SCTFRAME_NO_C && SCTFRAME_NO_P
-void *sctframe_add(sctframe_t *f, void *ptr) 
-#elif SCTFRAME_NO_C
-void *P(sctframe_t *f, void *ptr) 
-#else
-void *C(sctframe_t *f, void *ptr) 
-#endif
+
+void *sctframe_add_(sctframe_t *f, ...) 
 {
-    if (!scta_push(f->addresses, ptr)) {
+    struct record r;
+    
+    va_list ap;
+    va_start(ap, f);
+    
+    if (!(r.address = va_arg(ap, void *))) goto EXIT;
+    r.freef = va_arg(ap, void (*)(void *));
+    
+    
+    if (!scta_push(f->records, r)) {
         // could not store array
-        return NULL;
+        r.address = NULL;
+        goto EXIT;
     }
-    return ptr;
+    
+    EXIT:
+    va_end(ap);
+    return r.address;
 }
 
 void sctframe_free(sctframe_t *f) {
-    for (int i = 0; i < scta_length(f->addresses); ++i) free(f->addresses[i]);
-    scta_free(f->addresses);
+    for (int i = 0; i < scta_length(f->records); ++i) {
+        if (f->records[i].freef) f->records[i].freef(f->records[i].address);
+        else free(f->records[i].address);
+    }
+    scta_free(f->records);
     free(f);
 }
 
 extern FILE *sctframe_config_debug;
 extern int sctframe_config_version[3];
 
+struct record {
+    void *address;
+    void (*freef)(void *);
+};
+
 typedef struct {
-    void **addresses;
+    struct record *records;
 } sctframe_t;
 
 
 sctframe_t *sctframe_new();
-
-#if SCTFRAME_NO_C && SCTFRAME_NO_P
-void *sctframe_add(sctframe_t *f, void *ptr);
-#elif SCTFRAME_NO_C
-void *P(sctframe_t *f, void *ptr);
-#else
-void *C(sctframe_t *f, void *ptr);
-#endif
-
+void *sctframe_add_(sctframe_t *f, ...);
 void sctframe_free(sctframe_t *f);
 
+#define C(f, ...) (sctframe_add_(f, __VA_ARGS__, NULL))
+
 #endif
 
 #include "sctframe.h"
 
+
+void freecustom(void *ptr){
+    free( (char *) ptr-4);
+}
+
 int main (int argc, char **argv){
     sctframe_t * f = sctframe_new();
     
     assert(C(f, malloc(100)));
     assert(C(f, malloc(100)));
     assert(C(f, malloc(100)));
+    assert(C(f, (char *) malloc(100)+4, freecustom));
+    assert(C(f, (char *) malloc(100)+4, freecustom));
     
     sctframe_free(f);
     
+    
+    
     printf("sctframe version (%d:%d:%d) ok. (compiled on %s)\n", 
         sctframe_config_version[0], sctframe_config_version[1], 
         sctframe_config_version[2], __TIMESTAMP__);
+name=ml
+
+test: sct$(name).* test.c
+	gcc -o test -std=c99 -pedantic -g -Wall -I../str -I../a -I../os sct$(name).c ../str/sctstr.c ../os/sctos.c ../a/scta.c test.c
+
+memcheck: test
+	valgrind --tool=memcheck ./test
+
+clean:
+	rm test
+/*
+
+    sctml: Usefull HTML Routines
+    Sulaiman (seininn) Mustafa
+    Date: 2014-01-21
+    
+*/
+
+#define _POSIX_C_SOURCE 200809L
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "sctstr.h"
+#include "sctos.h"
+#include "scta.h"
+
+
+
+FILE *sctml_config_debug = NULL;
+int sctml_config_version[3] = {1, 0, 1};
+
+char *sctml_percent_encode(char *s, char *exceptions){
+    // implemented what I needed, prob. doesn't conferm to spec. Fix later
+    char *out = NULL;
+    
+    if (!exceptions) exceptions = "";
+    
+    for (;*s;++s) {
+        if ((*s >= 0x20 && *s < 0x30) && !strchr(exceptions, *s)) {
+            char buf[4];
+            snprintf(buf, 4, "%%%x", *s);
+            sctstr_append(&out, buf);
+        }
+        else sctstr_append(&out, (char [2]) {*s, 0});
+    }
+    return out;
+}
+
+char *sctml_xml_escape(char *s, char *exceptions){
+    // implemented what I needed, prob. doesn't conferm to spec. Fix later
+    char *out = NULL, *ptr;
+    char *list_in = "\"'<>&";
+    char *list_out[] = {"quot", "apos", "lt", "gt", "amp"};
+    
+    if (!exceptions) exceptions = "";
+    
+    for (;*s;++s) {
+        if ((ptr = strchr(list_in, *s)) && !strchr(exceptions, *s)) {
+            char buf[7] = {0};
+            strcat(buf, "&");
+            strcat(buf, list_out[ptr-list_in]);
+            strcat(buf, ";");
+            sctstr_append(&out, buf);
+        }
+        else sctstr_append(&out, (char [2]) {*s, 0});
+    }
+    return out;    
+}
+
+
+char **sctml_get_tags(char *string, char *tag){
+    #define ERROR_PROC {\
+        scta_free(opening);\
+        scta_free(closing);\
+        for (int i = 0; i < scta_length(list); ++i) free(list[i]);\
+        scta_free(list);\
+        return NULL;\
+    }
+        
+    #define OP_JUMP_CALC {\
+        ++c;\
+        i+=opening_length;\
+        {\
+            char *tc = strstr(string+i, ">");\
+            if (tc) {\
+                i=tc-string;\
+            }\
+            else ERROR_PROC\
+        }\
+    }
+        
+    
+    
+    int tag_length = strlen(tag);
+    
+    char *opening, *closing;
+    int opening_length, closing_length;
+    
+    char *t;
+    
+    // <tag
+    t = scta_new(char);
+    scta_push_array(t, "<", 1);
+    scta_push_array(t, tag, tag_length+1);
+    opening = t;
+    opening_length = tag_length+1;
+    
+    // </tag>
+    t = scta_new(char);
+    scta_push_array(t, "</", 2);
+    scta_push_array(t, tag, tag_length);
+    scta_push_array(t, ">", 2);
+    closing = t;
+    closing_length = tag_length+3;
+    
+    
+    char **list = scta_new(char *);
+
+    while (*string) {
+        // first occurence
+        int c = 0; // match counter 
+        int i = 0; // index
+        
+        string = strstr(string, opening);
+        
+        // if not found break, else skip to after opining string
+        if (!string) break;
+        else OP_JUMP_CALC
+
+        
+        // ignore submatches
+        while (*(string+i) && c) {
+            if (!strncmp(string+i, opening, opening_length)) {
+                OP_JUMP_CALC
+                continue;
+            }
+            if (!strncmp(string+i, closing, closing_length)) {
+                --c;
+                i+=closing_length;
+                continue;
+            }
+            ++i;
+        }
+        
+        if (c) {
+            //error
+            ERROR_PROC
+        }
+        if (i) { //match
+            char *p = malloc(i+1);
+            if (!p) {
+                //error
+                ERROR_PROC
+            }
+            strncpy(p, string, i);
+            p[i] = 0;
+            scta_push(list, p);
+        }
+        
+        string = string+i;
+    }
+    scta_free(opening);
+    scta_free(closing);
+    scta_push(list, NULL);
+    return list;
+}
+
+void sctml_free_tags(char **list) {
+    if (scta_length(list)) for (int i = 0; list[i]; ++i) free(list[i]);
+    scta_free(list);
+}
+
+
+
+
+
+
+char *sctml_strip_tags(char *tag){
+    char *start = strchr(tag, '>');
+    char *end = strrchr(tag, '<');
+    
+    if (!start || !end) {
+        return NULL;
+    }
+    
+    if (start > end) {
+        return NULL;
+    }
+    
+    return strndup(start+1, end-start-1);
+}
+
+
+
+char **sctml_get_tags_from_file(char *filename, char *tag){
+    // Also consider using lim for a more robust method (will be equivilant to js getTextContent)
+    // HERE
+    char *buf;
+    if (!sctos_load(filename, &buf)) {
+        if (sctml_config_debug) fprintf(sctml_config_debug, "failed to load `%s'. enable sctos debuging for further information.\n", filename);
+        return NULL;
+    }
+    char **ret = sctml_get_tags(buf, tag);
+    free(buf);
+    return ret;
+}
+
+/*
+
+    sctml: Usefull XML/HTML Routines
+    Sulaiman (seininn) Mustafa
+    Date: 2014-01-21
+    
+*/
+
+#ifndef sctml_H
+#define sctml_H
+
+#include <stdbool.h>
+#include <stdio.h>
+
+extern FILE *sctml_config_debug;
+extern int sctml_config_version[3];
+
+
+char **sctml_get_tags(char *string, char *tag);
+char **sctml_get_tags_from_file(char *filename, char *tag);
+char *sctml_strip_tags(char *tag);
+void sctml_free_tags(char **list);
+
+char *sctml_percent_encode(char *s, char *exceptions);
+char *sctml_xml_escape(char *s, char *exceptions);
+
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+
+#include "sctml.h"
+#include "scta.h"
+
+int main (int argc, char **argv){
+    char *p[6];
+    assert(!strcmp(p[0]=sctml_percent_encode(" !\"#$%&'()*+,-./", NULL), 
+        "%20%21%22%23%24%25%26%27%28%29%2a%2b%2c%2d%2e%2f"));
+    assert(!strcmp(p[1]=sctml_percent_encode("a s!d\"f#g$h%j&k'l(z)x*c+v,b-n.m/q", NULL), 
+        "a%20s%21d%22f%23g%24h%25j%26k%27l%28z%29x%2ac%2bv%2cb%2dn%2em%2fq"));
+    assert(!strcmp(p[2]=sctml_percent_encode(" !\"#$%&'()*+,-./", ""), 
+        "%20%21%22%23%24%25%26%27%28%29%2a%2b%2c%2d%2e%2f"));
+    assert(!strcmp(p[3]=sctml_percent_encode(" !\"#$%&'()*+,-./", " ()+ /"), 
+        " %21%22%23%24%25%26%27()%2a+%2c%2d%2e/"));
+        
+    assert(!strcmp(p[4]=sctml_xml_escape("<>&\"'", NULL), 
+        "&lt;&gt;&amp;&quot;&apos;"));
+    assert(!strcmp(p[5]=sctml_xml_escape("<>&\"'", ">"), 
+        "&lt;>&amp;&quot;&apos;"));
+    
+    
+    for (int i= 0; i< 6; ++i) free(p[i]);
+    
+    char **list = sctml_get_tags("<test id='temp'>111</test><test>22</test>  <test>3</test>", "test");
+    assert(list);
+    assert(!strcmp(list[0], "<test id='temp'>111</test>"));
+    assert(!strcmp(list[1], "<test>22</test>"));
+    assert(!strcmp(list[2], "<test>3</test>"));
+    assert(!list[3]);
+    sctml_free_tags(list);
+    
+    list = sctml_get_tags("   <test>3</test>    ", "test");
+    assert(list);
+    assert(!strcmp(list[0], "<test>3</test>"));
+    assert(!list[1]);
+    sctml_free_tags(list);
+    
+    list = sctml_get_tags("   <test><test>hi mom</test></test> <test></test>   ", "test");
+    assert(list);
+    assert(!strcmp(list[0], "<test><test>hi mom</test></test>"));
+    assert(!strcmp(list[1], "<test></test>"));
+    assert(!list[2]);
+    sctml_free_tags(list);
+    
+    assert(!sctml_get_tags("   <test><test>hi mom</test></test> <test>   ", "test"));
+    assert(!sctml_get_tags("   <test><test>hi mom</test>   ", "test"));
+    
+    list = sctml_get_tags_from_file("test.d/test.xml", "title");
+    assert(list);
+    assert(!strcmp(list[0], "<title>some text</title>"));
+    assert(!list[1]);
+    sctml_free_tags(list);
+    
+    
+    
+    char *z;
+    #define TEST_STRIP_TAGS(TAG, RESULT)\
+    z=sctml_strip_tags(TAG);\
+    assert(!(!RESULT && z));\
+    assert(!(RESULT && !z));\
+    if (RESULT) assert(!(strcmp(z, RESULT?RESULT:"(NULL)")));\
+    free(z);
+    
+    TEST_STRIP_TAGS("<jaja>1</jaja>", "1")
+    TEST_STRIP_TAGS("<jaja some=stuff>22</jaja>", "22")
+    TEST_STRIP_TAGS("<jaja some=stuff></jaja>", "")
+    TEST_STRIP_TAGS("<jaja some=stuff>", NULL)
+    
+    
+    
+    
+    
+    printf("sctml version (%d:%d:%d) ok. (compiled on %s)\n", 
+        sctml_config_version[0], sctml_config_version[1], 
+        sctml_config_version[2], __TIMESTAMP__);
+    return 0;
+}

ml/test.d/test.xml

+<test>
+	<title>some text</title>
+</test>

run-tests.sh

-#!/bin/bash
-
-test(){
-	cd "$1"
-	printf "\e[1;31m"
-	make -s test 2>&1 > /dev/null || {
-		echo "make failed for '$1'."
-		printf "\e[0m"
-		exit 1
-	}
-	printf "\e[0m"
-
-	printf "\e[1m"
-	./test || exit 1
-	printf "\e[0m"
-	make -s clean 2>&1 > /dev/null
-	cd - > /dev/null
-
-}
-
-test a
-test frame 
-test time
-test os
-test xml
+#!/bin/bash
+
+stderr(){
+    echo "$1" 1>&2
+}
+
+stddbg(){
+    [[ $debug ]] && printf "$1" 1>&2
+}
+
+
+[[ -d "$1" ]] || {
+    stderr "'$1' is not a directory."
+    exit 1
+}
+
+[[ "$2" ]] || {
+    stderr "search for what?"
+    exit 1
+}
+
+loc=$(grep -nr "sctman:$2" "$1")
+
+[[ "$loc" ]] || {
+    echo "'$2' was not found in '$1'"
+    exit 1
+}
+
+filename=$(echo "$loc" | grep -o '^[a-z\./]*:' | tr -d ':')
+lineno=$(echo "$loc" | grep -o ':[0-9]*:' | tr -d ':')
+#((lineno++))
+
+HEADER_COLOR=''
+TYPE_COLOR=''
+TITLE_COLOR=''
+SELECTED_COLOR=''
+RESET=''
+
+typecolor() {
+    sed -re 's/( |^ *|\()('"$1"')( |\)|\**\))/'"$TYPE_COLOR"'&'"$RESET"'/g'
+}
+
+tail -n "+$lineno" "$filename" | sed '/\*\//{q}' | head -n -1 | {
+     #sed -re "s/^sctman.*/$HEADER_COLOR&$RESET/g" | 
+     #sed -re "s/[^:]$2/$SELECTED_COLOR&$RESET/g" | 
+     #typecolor "int" | 
+     #typecolor "long" |
+     #typecolor "char" | 
+     #typecolor "bool" | 
+     #typecolor "float" |
+     #typecolor "struct( [a-zA-Z_]+)* ?\**" | 
+     sed -re 's/^[A-Z]+ *$/'"$TITLE_COLOR"'&'"$RESET"'/g' 
+} | less -R
+
+
+
+#!/bin/bash
+
+debug=o
+
+cprintf(){
+    printf "$2$1\e[0m"
+}
+
+stderr(){
+    echo "$1" 1>&2
+}
+
+stddbg(){
+    [[ $debug ]] && printf "$1" 1>&2
+}
+
+lineinfile(){
+    grep -e "^$1$" $2 > /dev/null
+}
+
+resolve(){
+    while read d; do
+         stddbg "resolving '$d': "
+        
+        lineinfile "$d" $processed && {
+            stddbg "already processed.\n"
+            continue
+        }
+        [[ -d "$base/$d" ]] || {
+            cprintf "Abort: '$dep' is not a sct module!\n" "\e[1;31m"
+            exit 1
+        }
+        
+        echo "$d" >> $processed # insert first to avoid circular dependencies
+        stddbg "scannng/recursing:\n"
+            
+        cat "$base/$d/sct$d.c" "$base/$d/sct$d.h" | \
+            grep -e '^#include "sct.*\.h"' | grep -o 'sct[a-z]*' | sed 's/^sct//g' | \
+                resolve
+        
+    done
+}
+
+
+
+help="--- help message ---"
+
+
+
+# application starts here
+
+# cross-process lists
+selected=$(mktemp)
+processed=$(mktemp)
+
+
+# first argument must be the sct directory
+[[ -d "$1" ]] || {
+    stderr "'$1' is not a directory."
+    stderr "$help"
+    exit 1
+}
+
+base="$1"
+
+# push all supplied module names in  selected
+shift
+while [[ "$1" ]]; do
+    echo "$1" >> $selected
+    shift
+done
+
+# solve dependencies
+cat $selected | resolve
+
+
+# sorting doe comm(1)
+sort -o $selected $selected
+sort -o $processed $processed 
+
+#output
+cprintf "Selected modules:\n" "\e[1m"
+echo "        "$(cat $selected)
+
+diffmod="$(comm -2 -3 $processed $selected)"
+[[ $diffmod ]] && {
+    cprintf "Required dependencies:\n" "\e[1m"
+    echo "        "$(comm -2 -3 $processed $selected)
+}
+
+rm "$selected"
+cprintf "Retrieving modules...\n" "\e[1m"
+
+
+
+# COPYING MODULES
+while read dep; do
+    printf "\tretrieving $dep .c/.h files'\n"
+    printf "\e[1;31m"
+    
+    cp "$base/$dep/sct$dep.c" "$base/$dep/sct$dep.h" . || {
+        printf "\n\nAbort\n"
+        printf "\e[0m"
+        exit 1
+    }
+    printf "\e[0m"
+done < $processed
+
+
+    
+cprintf "ok\n" "\e[1;32m"
+    
+
+
+#!/bin/bash
+
+test(){
+	cd "$1"
+	printf "\e[1;31m"
+	make -s test 2>&1 > /dev/null || {
+		echo "make failed for '$1'."
+		printf "\e[0m"
+		exit 1
+	}
+	printf "\e[0m"
+
+	printf "\e[1m"
+	./test || exit 1
+	printf "\e[0m"
+	make -s clean 2>&1 > /dev/null
+	cd - > /dev/null
+
+}
+
+test "a"
+test "frame"
+test "time"
+test "os"
+test "ml"

xml/DEPENDENCIES

-sctstr
-sctos
-scta

xml/Makefile

-name=ml
-
-test: sct$(name).* test.c
-	gcc -o test -std=c99 -pedantic -g -Wall -I../str -I../a -I../os sct$(name).c ../str/sctstr.c ../os/sctos.c ../a/scta.c test.c
-
-memcheck: test
-	valgrind --tool=memcheck ./test
-
-clean:
-	rm test

xml/sctml.c

-/*
-
-    sctml: Usefull HTML Routines
-    Sulaiman (seininn) Mustafa
-    Date: 2014-01-21
-    
-*/
-
-#define _POSIX_C_SOURCE 200809L
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdbool.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <unistd.h>
-#include <errno.h>
-
-#include "sctstr.h"
-#include "sctos.h"
-#include "scta.h"
-
-
-
-FILE *sctml_config_debug = NULL;
-int sctml_config_version[3] = {1, 0, 1};
-
-char *sctml_percent_encode(char *s, char *exceptions){
-    // implemented what I needed, prob. doesn't conferm to spec. Fix later
-    char *out = NULL;
-    
-    if (!exceptions) exceptions = "";
-    
-    for (;*s;++s) {
-        if ((*s >= 0x20 && *s < 0x30) && !strchr(exceptions, *s)) {
-            char buf[4];
-            snprintf(buf, 4, "%%%x", *s);
-            sctstr_append(&out, buf);
-        }
-        else sctstr_append(&out, (char [2]) {*s, 0});
-    }
-    return out;
-}
-
-char *sctml_xml_escape(char *s, char *exceptions){
-    // implemented what I needed, prob. doesn't conferm to spec. Fix later
-    char *out = NULL, *ptr;
-    char *list_in = "\"'<>&";
-    char *list_out[] = {"quot", "apos", "lt", "gt", "amp"};
-    
-    if (!exceptions) exceptions = "";
-    
-    for (;*s;++s) {
-        if ((ptr = strchr(list_in, *s)) && !strchr(exceptions, *s)) {
-            char buf[7] = {0};
-            strcat(buf, "&");
-            strcat(buf, list_out[ptr-list_in]);
-            strcat(buf, ";");
-            sctstr_append(&out, buf);
-        }
-        else sctstr_append(&out, (char [2]) {*s, 0});
-    }
-    return out;    
-}
-
-
-char **sctml_tag_content(char *string, char *tag){
-    #define ERROR_PROC {\
-        scta_free(opening);\
-        scta_free(closing);\
-        for (int i = 0; i < scta_length(list); ++i) free(list[i]);\
-        scta_free(list);\
-        return NULL;\
-    }
-        
-    #define OP_JUMP_CALC {\
-        ++c;\
-        i+=opening_length;\
-        {\
-            char *tc = strstr(string+i, ">");\
-            if (tc) {\
-                i=tc-string;\
-            }\
-            else ERROR_PROC\
-        }\
-    }
-        
-    
-    
-    int tag_length = strlen(tag);
-    
-    char *opening, *closing;
-    int opening_length, closing_length;
-    
-    char *t;
-    
-    // <tag
-    t = scta_new(char);
-    scta_push_array(t, "<", 1);
-    scta_push_array(t, tag, tag_length+1);
-    opening = t;
-    opening_length = tag_length+1;
-    
-    // </tag>
-    t = scta_new(char);
-    scta_push_array(t, "</", 2);
-    scta_push_array(t, tag, tag_length);
-    scta_push_array(t, ">", 2);
-    closing = t;
-    closing_length = tag_length+3;
-    
-    
-    char **list = scta_new(char *);
-
-    while (*string) {
-        // first occurence
-        int c = 0; // match counter 
-        int i = 0; // index
-        
-        string = strstr(string, opening);
-        
-        // if not found break, else skip to after opining string
-        if (!string) break;
-        else OP_JUMP_CALC
-
-        
-        // ignore submatches
-        while (*(string+i) && c) {
-            if (!strncmp(string+i, opening, opening_length)) {
-                OP_JUMP_CALC
-                continue;
-            }
-            if (!strncmp(string+i, closing, closing_length)) {
-                --c;
-                i+=closing_length;
-                continue;
-            }
-            ++i;
-        }
-        
-        if (c) {
-            //error
-            ERROR_PROC
-        }
-        if (i) { //match
-            char *p = malloc(i+1);
-            if (!p) {
-                //error
-                ERROR_PROC
-            }
-            strncpy(p, string, i);
-            p[i] = 0;
-            scta_push(list, p);
-        }
-        
-        string = string+i;
-    }
-    scta_free(opening);
-    scta_free(closing);
-    scta_push(list, NULL);
-    return list;
-}
-
-void sctml_tag_content_free(char **list) {
-    if (scta_length(list)) for (int i = 0; list[i]; ++i) free(list[i]);
-    scta_free(list);
-}
-
-char **sctml_tag_content_from_file(char *filename, char *tag){
-    // Also consider using lim for a more robust method (will be equivilant to js getTextContent)
-    // HERE
-    char *buf;
-    if (!sctos_load(filename, &buf)) {
-        if (sctml_config_debug) fprintf(sctml_config_debug, "failed to load `%s'. enable sctos debuging for further information.\n", filename);
-        return NULL;
-    }
-    char **ret = sctml_tag_content(buf, tag);
-    free(buf);
-    return ret;
-}
-

xml/sctml.h

-/*
-
-    sctml: Usefull XML/HTML Routines
-    Sulaiman (seininn) Mustafa
-    Date: 2014-01-21
-    
-*/
-
-#ifndef sctml_H
-#define sctml_H
-
-#include <stdbool.h>
-#include <stdio.h>
-
-extern FILE *sctml_config_debug;
-extern int sctml_config_version[3];
-
-char **sctml_tag_content_from_file(char *filename, char *tag);
-
-char **sctml_tag_content(char *string, char *tag);
-void sctml_tag_content_free(char **list);
-
-char *sctml_percent_encode(char *s, char *exceptions);
-char *sctml_xml_escape(char *s, char *exceptions);
-
-#endif

xml/test.c

-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <assert.h>
-#include <string.h>
-
-#include "sctml.h"
-#include "scta.h"
-
-int main (int argc, char **argv){
-    char *p[6];
-    assert(!strcmp(p[0]=sctml_percent_encode(" !\"#$%&'()*+,-./", NULL), 
-        "%20%21%22%23%24%25%26%27%28%29%2a%2b%2c%2d%2e%2f"));
-    assert(!strcmp(p[1]=sctml_percent_encode("a s!d\"f#g$h%j&k'l(z)x*c+v,b-n.m/q", NULL), 
-        "a%20s%21d%22f%23g%24h%25j%26k%27l%28z%29x%2ac%2bv%2cb%2dn%2em%2fq"));
-    assert(!strcmp(p[2]=sctml_percent_encode(" !\"#$%&'()*+,-./", ""), 
-        "%20%21%22%23%24%25%26%27%28%29%2a%2b%2c%2d%2e%2f"));
-    assert(!strcmp(p[3]=sctml_percent_encode(" !\"#$%&'()*+,-./", " ()+ /"), 
-        " %21%22%23%24%25%26%27()%2a+%2c%2d%2e/"));
-        
-    assert(!strcmp(p[4]=sctml_xml_escape("<>&\"'", NULL), 
-        "&lt;&gt;&amp;&quot;&apos;"));
-    assert(!strcmp(p[5]=sctml_xml_escape("<>&\"'", ">"), 
-        "&lt;>&amp;&quot;&apos;"));
-    
-    
-    for (int i= 0; i< 6; ++i) free(p[i]);
-    
-    char **list = sctml_tag_content("<test id='temp'>111</test><test>22</test>  <test>3</test>", "test");
-    assert(list);
-    assert(!strcmp(list[0], "<test id='temp'>111</test>"));
-    assert(!strcmp(list[1], "<test>22</test>"));
-    assert(!strcmp(list[2], "<test>3</test>"));
-    assert(!list[3]);
-    sctml_tag_content_free(list);
-    
-    list = sctml_tag_content("   <test>3</test>    ", "test");
-    assert(list);
-    assert(!strcmp(list[0], "<test>3</test>"));
-    assert(!list[1]);
-    sctml_tag_content_free(list);
-    
-    list = sctml_tag_content("   <test><test>hi mom</test></test> <test></test>   ", "test");
-    assert(list);
-    assert(!strcmp(list[0], "<test><test>hi mom</test></test>"));
-    assert(!strcmp(list[1], "<test></test>"));
-    assert(!list[2]);
-    sctml_tag_content_free(list);
-    
-    
-    assert(!sctml_tag_content("   <test><test>hi mom</test></test> <test>   ", "test"));
-    assert(!sctml_tag_content("   <test><test>hi mom</test>   ", "test"));
-    
-    list = sctml_tag_content_from_file("test.d/test.xml", "title");
-    assert(list);
-    assert(!strcmp(list[0], "<title>some text</title>"));
-    assert(!list[1]);
-    sctml_tag_content_free(list);
-    
-    
-    printf("sctml version (%d:%d:%d) ok. (compiled on %s)\n", 
-        sctml_config_version[0], sctml_config_version[1], 
-        sctml_config_version[2], __TIMESTAMP__);
-    return 0;
-}

xml/test.d/test.xml

-<test>
-	<title>some text</title>
-</test>