[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemacs-commit] qemacs clang.c
From: |
Charlie Gordon |
Subject: |
[Qemacs-commit] qemacs clang.c |
Date: |
Sat, 15 Dec 2007 09:57:21 +0000 |
CVSROOT: /cvsroot/qemacs
Module name: qemacs
Changes by: Charlie Gordon <chqrlie> 07/12/15 09:57:21
Modified files:
. : clang.c
Log message:
improved colorizer:
- simplified preprocessing directives, handle comments
- colorize char constants and strings with different styles
- handle javascript <!-- comments
- handle numbers
- better support for cast detection
more code simplifications
use colorizer for do_c_forward_block: should make this command non mode
specific
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/clang.c?cvsroot=qemacs&r1=1.13&r2=1.14
Patches:
Index: clang.c
===================================================================
RCS file: /cvsroot/qemacs/qemacs/clang.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- clang.c 12 Dec 2007 02:51:05 -0000 1.13
+++ clang.c 15 Dec 2007 09:57:21 -0000 1.14
@@ -30,12 +30,12 @@
"|char|double|float|int|long|unsigned|short|signed|void|var|"
"_Bool|_Complex|_Imaginary";
-static int get_c_keyword(char *buf, int buf_size, unsigned int **pp)
+#if 0
+static int get_c_keyword(char *buf, int buf_size, unsigned int *p)
{
- unsigned int *p, c;
+ unsigned int c;
char *q;
- p = *pp;
c = *p;
q = buf;
if ((c >= 'a' && c <= 'z') ||
@@ -52,24 +52,24 @@
(c >= '0' && c <= '9'));
}
*q = '\0';
- *pp = p;
return q - buf;
}
+#endif
/* colorization states */
enum {
C_COMMENT = 1,
- C_COMMENT1,
- C_STRING,
- C_STRING_Q,
- C_PREPROCESS,
+ C_COMMENT1 = 2,
+ C_STRING = 4,
+ C_STRING_Q = 8,
+ C_PREPROCESS = 16,
};
void c_colorize_line(unsigned int *buf, int len,
int *colorize_state_ptr, __unused__ int state_only)
{
- int c, state, l, type_decl;
- unsigned int *p, *p_start, *p1;
+ int c, state, style, klen, type_decl;
+ unsigned int *p, *p_start, *p1, *p2;
char kbuf[32];
state = *colorize_state_ptr;
@@ -77,137 +77,172 @@
p_start = p;
type_decl = 0;
c = 0; /* turn off stupid egcs-2.91.66 warning */
+ style = 0;
+ if (state) {
/* if already in a state, go directly in the code parsing it */
- switch (state) {
- case C_COMMENT:
+ if (state & C_PREPROCESS)
+ style = QE_STYLE_PREPROCESS;
+ if (state & C_COMMENT)
goto parse_comment;
- case C_COMMENT1:
+ if (state & C_COMMENT1)
goto parse_comment1;
- case C_STRING:
- case C_STRING_Q:
+ if (state & C_STRING)
goto parse_string;
- case C_PREPROCESS:
- goto parse_preprocessor;
- default:
- break;
+ if (state & C_STRING_Q)
+ goto parse_string_q;
}
for (;;) {
p_start = p;
- c = *p;
+ c = *p++;
+
switch (c) {
case '\n':
+ p--;
goto the_end;
case '/':
- p++;
+ if (*p == '/') {
+ /* line comment */
+ parse_comment1:
+ state |= C_COMMENT1;
+ p = buf + len;
+ set_color(p_start, p, QE_STYLE_COMMENT);
+ goto the_end;
+ } else
if (*p == '*') {
/* normal comment */
p++;
- state = C_COMMENT;
parse_comment:
+ state |= C_COMMENT;
while (*p != '\n') {
if (p[0] == '*' && p[1] == '/') {
p += 2;
- state = 0;
+ state &= ~C_COMMENT;
break;
} else {
p++;
}
}
set_color(p_start, p, QE_STYLE_COMMENT);
- } else
- if (*p == '/') {
- /* line comment */
- parse_comment1:
- state = C_COMMENT1;
- p = buf + len;
- set_color(p_start, p, QE_STYLE_COMMENT);
- if (p > buf && (p[-1] & CHAR_MASK) != '\\')
- state = 0;
+ continue;
}
break;
- case '#':
- /* preprocessor */
- parse_preprocessor:
+ case '#': /* preprocessor */
state = C_PREPROCESS;
- /* incorrect if preprocessing line contains a comment */
- p = buf + len;
+ style = QE_STYLE_PREPROCESS;
+ break;
+ set_preprocessor:
set_color(p_start, p, QE_STYLE_PREPROCESS);
- if (p > buf && (p[-1] & CHAR_MASK) != '\\')
- state = 0;
- goto the_end;
- case 'L':
- if (p[1] == '\'') {
+ continue;
+ case 'L': /* wide character and string literals */
+ if (*p == '\'') {
p++;
- state = C_STRING_Q;
- goto string;
+ goto parse_string_q;
}
- if (p[1] == '\"') {
+ if (*p == '\"') {
p++;
- state = C_STRING;
- goto string;
+ goto parse_string;
}
goto normal;
- case '\'':
- state = C_STRING_Q;
- goto string;
- case '\"':
- /* strings/chars */
- state = C_STRING;
- string:
- p++;
- parse_string:
- /* XXX: separate styles for string and char const? */
- while (*p != '\n') {
+ case '\'': /* character constant */
+ parse_string_q:
+ state |= C_STRING_Q;
+ for (; *p != '\n'; p++) {
if (*p == '\\') {
p++;
if (*p == '\n')
break;
+ } else
+ if (*p == '\'') {
p++;
- } else if ((*p == '\'' && state == C_STRING_Q) ||
- (*p == '\"' && state == C_STRING)) {
+ state &= ~C_STRING_Q;
+ break;
+ }
+ }
+ if (state & C_PREPROCESS)
+ goto set_preprocessor;
+ set_color(p_start, p, QE_STYLE_STRING_Q);
+ continue;
+ case '\"': /* strings literal */
+ parse_string:
+ state |= C_STRING;
+ for (; *p != '\n'; p++) {
+ if (*p == '\\') {
p++;
- state = 0;
+ if (*p == '\n')
break;
- } else {
+ } else
+ if (*p == '\"') {
p++;
+ state &= ~C_STRING;
+ break;
}
}
+ if (state & C_PREPROCESS)
+ goto set_preprocessor;
set_color(p_start, p, QE_STYLE_STRING);
- break;
+ continue;
case '=':
- p++;
/* exit type declaration */
+ /* does not handle this: int i = 1, j = 2; */
type_decl = 0;
break;
+ case '<': /* JavaScript extension */
+ if (*p == '!' && p[1] == '-' && p[2] == '-')
+ goto parse_comment1;
+ break;
default:
normal:
+ if (state & C_PREPROCESS)
+ break;
+ if (c >= '0' && c <= '9') {
+ while (!(p & 0x7f) && (isalnum(*p) || *p == '.')) {
+ p++;
+ }
+ set_color(p_start, p, QE_STYLE_NUMBER);
+ continue;
+ }
if ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c == '_')) {
- /* XXX: should handle inplace and support :: */
- l = get_c_keyword(kbuf, sizeof(kbuf), &p);
- p1 = p;
- while (*p == ' ' || *p == '\t')
+ /* XXX: should support :: */
+ klen = 0;
+ p--;
+ do {
+ if (klen < countof(kbuf) - 1)
+ kbuf[klen++] = c;
p++;
+ c = *p;
+ } while ((c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c == '_') ||
+ (c >= '0' && c <= '9'));
+
+ kbuf[klen] = '\0';
+ p1 = p;
+ while (*p1 == ' ' || *p1 == '\t')
+ p1++;
+ p2 = p1;
+ while (*p2 == '*' || *p2 == ' ' || *p2 == '\t')
+ p2++;
if (strfind(c_keywords, kbuf, 0)) {
- set_color(p_start, p1, QE_STYLE_KEYWORD);
+ set_color(p_start, p, QE_STYLE_KEYWORD);
} else
if (strfind(c_types, kbuf, 0)
- || (l > 2 && kbuf[l - 2] == '_' && kbuf[l - 1] == 't')) {
+ || (klen > 2 && kbuf[klen - 2] == '_' && kbuf[klen - 1] ==
't')) {
/* c type */
/* if not cast, assume type declaration */
- if (*p != ')') {
+ if (*p2 != ')') {
type_decl = 1;
}
- set_color(p_start, p1, QE_STYLE_TYPE);
+ set_color(p_start, p, QE_STYLE_TYPE);
} else
if (*p == '(') {
/* function call */
/* XXX: different styles for call and definition */
- set_color(p_start, p1, QE_STYLE_FUNCTION);
+ set_color(p_start, p, QE_STYLE_FUNCTION);
} else {
/* assume typedef if starting at first column */
if (p_start == buf)
@@ -216,19 +251,22 @@
if (type_decl) {
if (p_start == buf) {
/* assume type if first column */
- set_color(p_start, p1, QE_STYLE_TYPE);
+ set_color(p_start, p, QE_STYLE_TYPE);
} else {
- set_color(p_start, p1, QE_STYLE_VARIABLE);
+ set_color(p_start, p, QE_STYLE_VARIABLE);
}
}
}
- } else {
- p++;
+ continue;
}
break;
}
+ set_color1(p_start, style);
}
the_end:
+ /* strip state if not overflowing from a comment */
+ if (!(state & C_COMMENT) && p > buf && ((p[-1] & CHAR_MASK) != '\\'))
+ state &= ~(C_COMMENT1 | C_PREPROCESS);
*colorize_state_ptr = state;
}
@@ -320,8 +358,7 @@
/* find start of line */
eb_get_pos(s->b, &line_num, &col_num, s->offset);
line_num1 = line_num;
- offset = s->offset;
- offset = eb_goto_bol(s->b, offset);
+ offset = eb_goto_bol(s->b, s->offset);
/* now find previous lines and compute indent */
pos = 0;
lpos = -1; /* position of the last instruction start */
@@ -333,9 +370,8 @@
if (offsetl == 0)
break;
line_num--;
- eb_prevc(s->b, offsetl, &offsetl);
- offsetl = eb_goto_bol(s->b, offsetl);
- len = get_colorized_line(s, buf, MAX_BUF_SIZE - 1, offsetl, line_num);
+ offsetl = eb_prev_line(s->b, offsetl);
+ len = get_colorized_line(s, buf, countof(buf), offsetl, line_num);
/* store indent position */
pos1 = find_indent1(s, buf);
p = buf + len;
@@ -455,7 +491,7 @@
}
end_parse:
/* compute special cases which depend on the chars on the current line */
- len = get_colorized_line(s, buf, MAX_BUF_SIZE - 1, offset, line_num1);
+ len = get_colorized_line(s, buf, countof(buf), offset, line_num1);
if (stack_ptr == 0) {
if (!pos && lpos >= 0) {
@@ -507,7 +543,7 @@
offset1 = offset;
insert_spaces(s, &offset1, pos);
if (s->offset == offset) {
- /* move to the inddentation if point was in indent space */
+ /* move to the indentation if point was in indent space */
s->offset = offset1;
}
}
@@ -578,16 +614,35 @@
static void do_c_forward_block(EditState *s, int dir)
{
+ unsigned int buf[MAX_BUF_SIZE];
char balance[MAX_LEVEL];
- int c, c1, offset, offset0, level;
+ int line_num, col_num, offset, len, pos, style, c, c1, level;
- /* XXX: should use colorization to deal with syntax */
+ eb_get_pos(s->b, &line_num, &col_num, s->offset);
+ offset = eb_goto_bol2(s->b, s->offset, &pos);
+ len = get_colorized_line(s, buf, countof(buf), offset, line_num);
+ style = buf[pos] >> STYLE_SHIFT;
level = 0;
- offset0 = offset = s->offset;
+
if (dir < 0) {
- for (; offset > 0;) {
- c = eb_prevc(s->b, offset, &offset);
- switch (c) {
+ for (;;) {
+ if (pos == 0) {
+ if (offset <= 0)
+ break;
+ line_num--;
+ offset = eb_prev_line(s->b, offset);
+ pos = get_colorized_line(s, buf, countof(buf), offset,
line_num);
+ continue;
+ }
+ c = buf[--pos];
+ if (style != c >> STYLE_SHIFT) {
+ if (style == 0)
+ continue;
+ style = 0;
+ if ((c >> STYLE_SHIFT) != 0)
+ continue;
+ }
+ switch (c &= CHAR_MASK) {
case ')':
c1 = '(';
goto push;
@@ -601,7 +656,7 @@
balance[level] = c1;
}
level++;
- continue;
+ break;
case '(':
case '[':
case '{':
@@ -614,20 +669,30 @@
if (level <= 0)
goto the_end;
}
- continue;
- default:
- continue;
+ break;
}
}
} else {
for (;;) {
- c = eb_nextc(s->b, offset, &offset);
- again:
- switch (c) {
- case '\n':
+ if (pos >= len) {
+ line_num++;
+ pos = 0;
+ offset = eb_next_line(s->b, offset);
if (offset >= s->b->total_size)
- goto the_end;
+ break;
+ len = get_colorized_line(s, buf, countof(buf), offset,
line_num);
+ continue;
+ }
+ c = buf[pos];
+ pos++;
+ if (style != c >> STYLE_SHIFT) {
+ if (style == 0)
+ continue;
+ style = 0;
+ if ((c >> STYLE_SHIFT) != 0)
continue;
+ }
+ switch (c &= CHAR_MASK) {
case '(':
c1 = ')';
goto push1;
@@ -641,7 +706,7 @@
balance[level] = c1;
}
level++;
- continue;
+ break;
case ')':
case ']':
case '}':
@@ -654,34 +719,15 @@
if (level <= 0)
goto the_end;
}
- continue;
- case '/':
- c = eb_nextc(s->b, offset, &offset);
- if (c == '/') {
- while ((c = eb_nextc(s->b, offset, &offset)) != '\n')
- continue;
- } else
- if (c == '*') {
- for (;;) {
- while ((c = eb_nextc(s->b, offset, &offset)) != '*') {
- if (offset >= s->b->total_size)
- goto the_end;
- }
- while ((c = eb_nextc(s->b, offset, &offset)) == '*')
- continue;
- if (c == '/')
break;
}
- continue;
- } else {
- goto again;
- }
- default:
- continue;
- }
}
}
the_end:
+ while (pos > 0) {
+ eb_nextc(s->b, offset, &offset);
+ pos--;
+ }
s->offset = offset;
}