src/highlighter.c

Mon, 13 Nov 2017 14:17:46 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 13 Nov 2017 14:17:46 +0100
changeset 62
3fff4c364ffc
parent 61
47a5fc33590a
child 67
5da2cb5aea6b
permissions
-rw-r--r--

removes build/ucx from makefile

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2016 Mike Becker. All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  *
    28  */
    30 #include "highlighter.h"
    32 #include <stdlib.h>
    33 #include <stdio.h>
    34 #include <string.h>
    35 #include <ctype.h>
    36 #include <ucx/string.h>
    37 #include <ucx/utils.h>
    39 static void put_htmlescaped(UcxBuffer *dest, char c) {
    40     if (c == '>') {
    41         ucx_buffer_puts(dest, "&gt;");
    42     } else if (c == '<') {
    43         ucx_buffer_puts(dest, "&lt;");
    44     } else if (c) {
    45         ucx_buffer_putc(dest, c);
    46     }
    47 }
    49 static void put_htmlescapedstr(UcxBuffer *dest, sstr_t s) {
    50     for (int i = 0 ; i < s.length ; i++) {
    51         put_htmlescaped(dest, s.ptr[i]);
    52     }
    53 }
    55 static int check_keyword(sstr_t word, const char** keywords) {
    56     for (int i = 0 ; keywords[i] ; i++) {
    57         if (sstrcmp(word, sstr((char*)keywords[i])) == 0) {
    58             return 1;
    59         }
    60     }
    61     return 0;
    62 }
    64 static int check_capsonly(sstr_t word) {
    65     for (size_t i = 0 ; i < word.length ; i++) {
    66         if (!isupper(word.ptr[i]) && !isdigit(word.ptr[i])
    67                 && word.ptr[i] != '_') {
    68             return 0;
    69         }
    70     }
    71     return 1;
    72 }
    74 /* Plaintext Highlighter */
    76 void c2html_plain_highlighter(char *src, UcxBuffer *dest,
    77         c2html_highlighter_data *hd) {
    78     while (*src && *src != '\n') {
    79         if (*src != '\r') {
    80             put_htmlescaped(dest, *src);
    81         }
    82         src++;
    83     }
    84     ucx_buffer_putc(dest, '\n');
    85 }
    87 /* C Highlighter */
    89 static const char* ckeywords[] = {
    90     "auto", "break", "case", "char", "const", "continue", "default", "do",
    91     "double", "else", "enum", "extern", "float", "for", "goto", "if", "int",
    92     "long", "register", "return", "short", "signed", "sizeof", "static",
    93     "struct", "switch", "typedef", "union", "unsigned", "void", "volatile",
    94     "while", NULL
    95 };
    97 void c2html_c_highlighter(char *src, UcxBuffer *dest,
    98         c2html_highlighter_data *hd) {
    99     /* reset buffers without clearing them */
   100     hd->primary_buffer->size = hd->primary_buffer->pos = 0;
   101     hd->secondary_buffer->size = hd->secondary_buffer->pos = 0;
   103     /* alias the buffers for better handling */
   104     UcxBuffer *wbuf = hd->primary_buffer;
   105     UcxBuffer *ifilebuf = hd->secondary_buffer;
   107     /* local information */
   108     size_t sp = (size_t)-1;
   109     int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0;
   110     char quote = '\0';
   111     int isescaping = 0;
   113     /* continue a multi line comment highlighting */
   114     if (hd->multiline_comment) {
   115         iscomment = 1;
   116         ucx_buffer_puts(dest, "<span class=\"c2html-comment\">");
   117     }
   119     char c;
   120     do {
   121         c = src[++sp];
   122         if (c == '\r') continue;
   124         /* comments */
   125         if (!isstring && c == '/') {
   126             if (hd->multiline_comment && sp > 0 && src[sp-1] == '*') {
   127                 iscomment = 0;
   128                 hd->multiline_comment = 0;
   129                 ucx_buffer_puts(dest, "/</span>");
   130                 continue;
   131             } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) {
   132                 iscomment = 1;
   133                 hd->multiline_comment = (src[sp+1] == '*');
   134                 ucx_buffer_puts(dest, "<span class=\"c2html-comment\">");
   135             }
   136         }
   138         if (iscomment) {
   139             if (c == '\n') {
   140                 ucx_buffer_puts(dest, "</span>\n");
   141             } else {
   142                 put_htmlescaped(dest, c);
   143             }
   144         } else if (isinclude) {
   145             if (c == '<') {
   146                 ucx_buffer_puts(dest,
   147                         "<span class=\"c2html-stdinclude\">&lt;");
   148             } else if (c == '\"') {
   149                 if (parseinclude) {
   150                     ucx_buffer_puts(dest, "\">");
   151                     ucx_buffer_write(ifilebuf->space, 1, ifilebuf->size, dest);
   152                     ucx_buffer_puts(dest, "\"</a>");
   153                     parseinclude = 0;
   154                 } else {
   155                     ucx_buffer_puts(dest,
   156                             "<a class=\"c2html-userinclude\" href=\"");
   157                     ucx_buffer_putc(ifilebuf, '\"');
   158                     parseinclude = 1;
   159                 }
   160             } else if (c == '>') {
   161                 ucx_buffer_puts(dest,  "&gt;</span>");
   162             } else {
   163                 if (parseinclude) {
   164                     ucx_buffer_putc(ifilebuf, c);
   165                 }
   166                 put_htmlescaped(dest, c);
   167             }
   168         } else {
   169             /* strings */
   170             if (!isescaping && (c == '\'' || c == '\"')) {
   171                 if (isstring) {
   172                     put_htmlescaped(dest, c);
   173                     if (c == quote) {
   174                         isstring = 0;
   175                         ucx_buffer_puts(dest, "</span>");
   176                     } else {
   177                         put_htmlescaped(dest, c);
   178                     }
   179                 } else {
   180                     isstring = 1;
   181                     quote = c;
   182                     ucx_buffer_puts(dest, "<span class=\"c2html-string\">");
   183                     put_htmlescaped(dest, c);
   184                 }
   185             } else {
   186                 if (isstring) {
   187                     put_htmlescaped(dest, c);
   188                 } else if (isalnum(c) ||  c == '_' || c == '#') {
   189                     /* buffer the current word */
   190                     ucx_buffer_putc(wbuf, c);
   191                 } else {
   192                     /* write buffered word, if any */
   193                     if (wbuf->size > 0) {
   194                         sstr_t word = sstrn(wbuf->space, wbuf->size);
   195                         int closespan = 1;
   196                         sstr_t typesuffix = ST("_t");
   197                         if (check_keyword(word, ckeywords)) {
   198                             ucx_buffer_puts(dest,
   199                                     "<span class=\"c2html-keyword\">");
   200                         } else if (sstrsuffix(word, typesuffix)) {
   201                             ucx_buffer_puts(dest,
   202                                 "<span class=\"c2html-type\">");
   203                         } else if (word.ptr[0] == '#') {
   204                             isinclude = !sstrcmp(word, S("#include"));
   205                             ucx_buffer_puts(dest,
   206                                 "<span class=\"c2html-directive\">");
   207                         } else if (check_capsonly(word)) {
   208                             ucx_buffer_puts(dest,
   209                                 "<span class=\"c2html-macroconst\">");
   210                         } else {
   211                             closespan = 0;
   212                         }
   213                         put_htmlescapedstr(dest, word);
   214                         if (closespan) {
   215                             ucx_buffer_puts(dest, "</span>");
   216                         }
   217                     }
   218                     wbuf->pos = wbuf->size = 0; /* reset word buffer */
   220                     /* write current character */
   221                     put_htmlescaped(dest, c);
   222                 }
   223             }
   225             isescaping = !isescaping & (c == '\\');
   226         }
   227     } while (c && c != '\n');
   228 }
   230 /* Java Highlighter */
   232 static const char* jkeywords[] = {
   233     "abstract", "continue", "for", "new", "switch", "assert", "default", "goto",
   234     "package", "synchronized", "boolean", "do", "if", "private", "this",
   235     "break", "double", "implements", "protected", "throw", "byte", "else",
   236     "import", "public", "throws", "case", "enum", "instanceof", "return",
   237     "transient", "catch", "extends", "int", "short", "try", "char", "final",
   238     "interface", "static", "void", "class", "finally", "long", "strictfp",
   239     "volatile", "const", "float", "native", "super", "while", NULL
   240 };
   242 void c2html_java_highlighter(char *src, UcxBuffer *dest,
   243         c2html_highlighter_data *hd) {
   244     /* reset buffers without clearing them */
   245     hd->primary_buffer->size = hd->primary_buffer->pos = 0;
   246     hd->secondary_buffer->size = hd->secondary_buffer->pos = 0;
   248     /* alias the buffers for better handling */
   249     UcxBuffer *wbuf = hd->primary_buffer;
   251     /* local information */
   252     size_t sp = (size_t)-1;
   253     int isstring = 0, iscomment = 0, isimport = 0;
   254     char quote = '\0';
   255     int isescaping = 0;
   257     if (hd->multiline_comment) {
   258         iscomment = 1;
   259         ucx_buffer_puts(dest, "<span class=\"c2html-comment\">");
   260     }
   262     char c;
   263     do {
   264         c = src[++sp];
   265         if (c == '\r') continue;
   267         /* comments */
   268         if (!isstring && c == '/') {
   269             if (hd->multiline_comment && sp > 0 && src[sp-1] == '*') {
   270                 iscomment = 0;
   271                 hd->multiline_comment = 0;
   272                 ucx_buffer_puts(dest, "/</span>");
   273                 continue;
   274             } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) {
   275                 iscomment = 1;
   276                 hd->multiline_comment = (src[sp+1] == '*');
   277                 ucx_buffer_puts(dest, "<span class=\"c2html-comment\">");
   278             }
   279         }
   281         if (iscomment) {
   282             if (c == '\n') {
   283                 ucx_buffer_puts(dest, "</span>\n");
   284             } else {
   285                 put_htmlescaped(dest, c);
   286             }
   287         } else if (isimport) {
   288             /* TODO: local imports */
   289         } else {
   290             /* strings */
   291             if (!isescaping && (c == '\'' || c == '\"')) {
   292                 if (isstring) {
   293                     put_htmlescaped(dest, c);
   294                     if (c == quote) {
   295                         isstring = 0;
   296                         ucx_buffer_puts(dest, "</span>");
   297                     } else {
   298                         put_htmlescaped(dest, c);
   299                     }
   300                 } else {
   301                     isstring = 1;
   302                     quote = c;
   303                     ucx_buffer_puts(dest,
   304                         "<span class=\"c2html-string\">");
   305                     put_htmlescaped(dest, c);
   306                 }
   307             } else {
   308                 if (isstring) {
   309                     put_htmlescaped(dest, c);
   310                 } else if (isalnum(c) || c == '_' || c == '@') {
   311                     /* buffer the current word */
   312                     ucx_buffer_putc(wbuf, c);
   313                 } else {
   314                     /* write buffered word, if any */
   315                     if (wbuf->size > 0) {
   316                         sstr_t word = sstrn(wbuf->space, wbuf->size);
   317                         int closespan = 1;
   318                         if (check_keyword(word, jkeywords)) {
   319                             ucx_buffer_puts(dest,
   320                                 "<span class=\"c2html-keyword\">");
   321                         } else if (isupper(word.ptr[0])) {
   322                             ucx_buffer_puts(dest,
   323                                 "<span class=\"c2html-type\">");
   324                         } else if (word.ptr[0] == '@') {
   325                             ucx_buffer_puts(dest,
   326                                 "<span class=\"c2html-directive\">");
   327                         } else if (check_capsonly(word)) {
   328                             ucx_buffer_puts(dest,
   329                                 "<span class=\"c2html-macroconst\">");
   330                         } else {
   331                             closespan = 0;
   332                         }
   333                         put_htmlescapedstr(dest, word);
   335                         if (closespan) {
   336                             ucx_buffer_puts(dest, "</span>");
   337                         }
   338                     }
   339                     wbuf->pos = wbuf->size = 0; /* reset buffer */
   341                     /* write current character */
   342                     put_htmlescaped(dest, c);
   343                 }
   344             }
   346             isescaping = !isescaping & (c == '\\');
   347         }
   348     } while (c && c != '\n');
   349 }

mercurial