mplisp

miniPicoLisp with FFI and modules for Buddy BDD library, OpenGL, Gtk and GMP
git clone https://logand.com/git/mplisp.git/
Log | Files | Refs

ht.c (5688B)


      1 /* 20sep07abu
      2  * (c) Software Lab. Alexander Burger
      3  */
      4 
      5 #include "pico.h"
      6 
      7 static char *HtOK[] = {
      8    "<b>",      "</b>",
      9    "<i>",      "</i>",
     10    "<u>",      "</u>",
     11    "<p>",      "</p>",
     12    "<pre>",    "</pre>",
     13    "<div ",    "</div>",
     14    "<font ",   "</font>",
     15    "<img ",    "</img>",
     16    "<br>", "<hr>", NULL
     17 };
     18 
     19 static bool findHtOK(char *s) {
     20    char **p, *q, *t;
     21 
     22    for (p = HtOK; *p; ++p)
     23       for (q = *p,  t = s;;) {
     24          if (*q != *t)
     25             break;
     26          if (*++q == '\0')
     27             return YES;
     28          if (*++t == '\0')
     29             break;
     30       }
     31    return NO;
     32 }
     33 
     34 // (ht:Prin 'sym ..) -> T
     35 any Prin(any x) {
     36    any y;
     37 
     38    while (isCell(x = cdr(x))) {
     39       if (isNum(y = EVAL(car(x))) || isCell(y) || isExt(y))
     40          prin(y);
     41       else {
     42          int c;
     43          char *p, *q, nm[bufSize(y)];
     44 
     45          bufString(y, nm);
     46          for (p = nm; *p;) {
     47             if (findHtOK(p) && (q = strchr(p,'>')))
     48                do
     49                   Env.put(*p++);
     50                while (p <= q);
     51             else {
     52                switch (*(byte*)p) {
     53                case '<':
     54                   outString("&lt;");
     55                   break;
     56                case '>':
     57                   outString("&gt;");
     58                   break;
     59                case '&':
     60                   outString("&amp;");
     61                   break;
     62                case '"':
     63                   outString("&quot;");
     64                   break;
     65                case 0xFF:
     66                   Env.put(0xEF);
     67                   Env.put(0xBF);
     68                   Env.put(0xBF);
     69                   break;
     70                default:
     71                   Env.put(c = *p);
     72                   if ((c & 0x80) != 0) {
     73                      Env.put(*++p);
     74                      if ((c & 0x20) != 0)
     75                         Env.put(*++p);
     76                   }
     77                }
     78                ++p;
     79             }
     80          }
     81       }
     82    }
     83    return T;
     84 }
     85 
     86 static void putHex(int c) {
     87    int n;
     88 
     89    if ((n = c >> 4 & 0xF) > 9)
     90       n += 7;
     91    Env.put(n + '0');
     92    if ((n = c & 0xF) > 9)
     93       n += 7;
     94    Env.put(n + '0');
     95 }
     96 
     97 static int getHex(any *p) {
     98    int n, m;
     99 
    100    n = firstByte(car(*p)),  *p = cdr(*p);
    101    if ((n -= '0') > 9)
    102       n -= 7;
    103    m = firstByte(car(*p)),  *p = cdr(*p);
    104    if ((m -= '0') > 9)
    105       m -= 7;
    106    return n << 4 | m;
    107 }
    108 
    109 static void htEncode(char *p) {
    110 	int c;
    111 
    112    while (c = *p++) {
    113       if (strchr(" \"#%&:;<=>?_", c))
    114          Env.put('%'), putHex(c);
    115       else {
    116          Env.put(c);
    117          if ((c & 0x80) != 0) {
    118             Env.put(*p++);
    119             if ((c & 0x20) != 0)
    120                Env.put(*p++);
    121          }
    122       }
    123    }
    124 }
    125 
    126 static void htFmt(any x) {
    127    any y;
    128 
    129    if (isNum(x))
    130       Env.put('+'),  prin(x);
    131    else if (isCell(x))
    132       do
    133          Env.put('_'),  htFmt(car(x));
    134       while (isCell(x = cdr(x)));
    135    else if (isNum(y = name(x))) {
    136       char nm[bufSize(x)];
    137 
    138       bufString(x, nm);
    139       if (isExt(x))
    140          Env.put('-'),  htEncode(nm);
    141       else if (hashed(x, hash(y), Intern))
    142          Env.put('$'),  htEncode(nm);
    143       else if (strchr("$+.", *nm)) {
    144          Env.put('%'), putHex(*nm);
    145          htEncode(nm+1);
    146       }
    147       else
    148          htEncode(nm);
    149    }
    150 }
    151 
    152 // (ht:Fmt 'any ..) -> sym
    153 any Fmt(any x) {
    154    int n, i;
    155    cell c[length(x = cdr(x))];
    156 
    157    for (n = 0;  isCell(x);  ++n, x = cdr(x))
    158       Push(c[n], EVAL(car(x)));
    159    begString();
    160    for (i = 0; i < n;) {
    161       htFmt(data(c[i]));
    162       if (++i != n)
    163          Env.put('&');
    164    }
    165    x = endString();
    166    if (n)
    167       drop(c[0]);
    168    return x;
    169 }
    170 
    171 // (ht:Pack 'lst) -> sym
    172 any Pack(any x) {
    173    int c;
    174    cell c1;
    175 
    176    x = EVAL(cadr(x));
    177    begString();
    178    Push(c1,x);
    179    while (isCell(x)) {
    180       if ((c = symChar(name(car(x)))) == '%')
    181          x = cdr(x),  Env.put(getHex(&x));
    182       else
    183          outName(car(x)), x = cdr(x);
    184    }
    185    return endString();
    186 }
    187 
    188 /*** Chunked Encoding ***/
    189 #define CHUNK 4000
    190 static int Cnt;
    191 static void (*Get)(void);
    192 static void (*Put)(int);
    193 static char Chunk[CHUNK];
    194 
    195 static int chrHex(void) {
    196    if (Chr >= '0' && Chr <= '9')
    197       return Chr - 48;
    198    else if (Chr >= 'A' && Chr <= 'F')
    199       return Chr - 55;
    200    else if (Chr >= 'a' && Chr <= 'f')
    201       return Chr - 87;
    202    else
    203       return -1;
    204 }
    205 
    206 static void chunkSize(void) {
    207    int n;
    208 
    209    if (!Chr)
    210       Get();
    211    if ((Cnt = chrHex()) >= 0) {
    212       while (Get(), (n = chrHex()) >= 0)
    213          Cnt = Cnt << 4 | n;
    214       while (Chr != '\n') {
    215          if (Chr < 0)
    216             return;
    217          Get();
    218       }
    219       Get();
    220       if (Cnt == 0) {
    221          Get();  // Skip '\r' of empty line
    222          Chr = 0;  // Discard '\n'
    223       }
    224    }
    225 }
    226 
    227 static void getChunked(void) {
    228    if (Cnt <= 0)
    229       Chr = -1;
    230    else {
    231       Get();
    232       if (--Cnt == 0) {
    233          Get(), Get();  // Skip '\n', '\r'
    234          chunkSize();
    235       }
    236    }
    237 }
    238 
    239 // (ht:In 'flg . prg) -> any
    240 any In(any x) {
    241    x = cdr(x);
    242    if (isNil(EVAL(car(x))))
    243       return prog(cdr(x));
    244    Get = Env.get,  Env.get = getChunked;
    245    chunkSize();
    246    x = prog(cdr(x));
    247    Env.get = Get;
    248    Chr = 0;
    249    return x;
    250 }
    251 
    252 static void wrChunk(void) {
    253    int i;
    254    char buf[16];
    255 
    256    sprintf(buf, "%x\r\n", Cnt);
    257    i = 0;
    258    do
    259       Put(buf[i]);
    260    while (buf[++i]);
    261    for (i = 0; i < Cnt; ++i)
    262       Put(Chunk[i]);
    263    Put('\r'), Put('\n');
    264 }
    265 
    266 static void putChunked(int c) {
    267    Chunk[Cnt++] = c;
    268    if (Cnt == CHUNK)
    269       wrChunk(),  Cnt = 0;
    270 }
    271 
    272 // (ht:Out 'flg . prg) -> any
    273 any Out(any x) {
    274    x = cdr(x);
    275    if (isNil(EVAL(car(x))))
    276       x = prog(cdr(x));
    277    else {
    278       Cnt = 0;
    279       Put = Env.put,  Env.put = putChunked;
    280       x = prog(cdr(x));
    281       if (Cnt)
    282          wrChunk();
    283       Env.put = Put;
    284       outString("0\r\n\r\n");
    285    }
    286    flush(OutFile);
    287    return x;
    288 }