ohcount
|
00001 // parser_macros.h written by Mitchell Foral. mitchell<att>caladbolg.net. 00002 // See COPYING for license information. 00003 00004 #ifndef OHCOUNT_PARSER_MACROS_H 00005 #define OHCOUNT_PARSER_MACROS_H 00006 00007 #include <stdio.h> 00008 #include <stdlib.h> 00009 00010 #include "languages.h" 00011 00016 typedef struct CallbackItem { 00021 const char *lang; 00022 00027 const char *entity; 00028 00030 int s; 00031 00033 int e; 00034 00036 void *udata; 00037 00039 struct CallbackItem *next; 00040 00041 } Callback; 00042 00044 Callback *callback_list_head = NULL; 00045 00047 Callback *callback_list_tail = NULL; 00048 00070 void enqueue(const char *lang, const char *entity, int s, int e, void *udata) { 00071 Callback *item = (Callback *) malloc(sizeof(Callback)); 00072 if (!item) printf("Failed to allocate memory for enqueued callback.\n"); 00073 00074 item->lang = lang; 00075 item->entity = entity; 00076 item->s = s; 00077 item->e = e; 00078 item->udata = udata; 00079 item->next = NULL; 00080 00081 if (!callback_list_head) { 00082 callback_list_head = item; 00083 callback_list_tail = item; 00084 } else { 00085 callback_list_tail->next = item; 00086 callback_list_tail = item; 00087 } 00088 } 00089 00091 void free_queue() { 00092 Callback *item = callback_list_head; 00093 while (item) { 00094 Callback *next = item->next; 00095 free(item); 00096 item = next; 00097 } 00098 callback_list_head = NULL; 00099 callback_list_tail = NULL; 00100 } 00101 00107 #define dequeue { \ 00108 inqueue = 0; \ 00109 line_start = last_line_start; \ 00110 line_contains_code = last_line_contains_code; \ 00111 whole_line_comment = last_whole_line_comment; \ 00112 } 00113 00119 #define ls { \ 00120 if (inqueue) { dequeue; } \ 00121 if (!line_start) line_start = ts; \ 00122 } 00123 00130 #define code { \ 00131 if (inqueue) { dequeue; } \ 00132 if (!line_contains_code && !line_start) line_start = ts; \ 00133 line_contains_code = 1; \ 00134 } 00135 00141 #define comment { \ 00142 if (inqueue) { dequeue; } \ 00143 if (!line_contains_code) { \ 00144 whole_line_comment = 1; \ 00145 if (!line_start) line_start = ts; \ 00146 } \ 00147 } 00148 00157 #define saw(lang) { \ 00158 seen = lang; \ 00159 whole_line_comment = 0; \ 00160 line_contains_code = 0; \ 00161 } 00162 00169 #define std_internal_newline(lang) { \ 00170 if (callback && p > line_start) { \ 00171 if (line_contains_code) { \ 00172 if (inqueue) \ 00173 enqueue(lang, "lcode", cint(line_start), cint(p), userdata); \ 00174 else \ 00175 callback(lang, "lcode", cint(line_start), cint(p), userdata); \ 00176 } else if (whole_line_comment) { \ 00177 if (inqueue) \ 00178 enqueue(lang, "lcomment", cint(line_start), cint(p), userdata); \ 00179 else \ 00180 callback(lang, "lcomment", cint(line_start), cint(p), userdata); \ 00181 } else { \ 00182 if (inqueue) \ 00183 enqueue(lang, "lblank", cint(line_start), cint(p), userdata); \ 00184 else \ 00185 callback(lang, "lblank", cint(line_start), cint(p), userdata); \ 00186 } \ 00187 } \ 00188 whole_line_comment = 0; \ 00189 line_contains_code = 0; \ 00190 line_start = p; \ 00191 } 00192 00201 #define emb_internal_newline(lang) { \ 00202 if (seen && seen != lang) \ 00203 std_internal_newline(seen) \ 00204 else \ 00205 std_internal_newline(lang) \ 00206 seen = 0; \ 00207 } 00208 00215 #define std_newline(lang) {\ 00216 if (inqueue) { dequeue; } \ 00217 if (callback && te > line_start) { \ 00218 if (line_contains_code) \ 00219 callback(lang, "lcode", cint(line_start), cint(te), userdata); \ 00220 else if (whole_line_comment) \ 00221 callback(lang, "lcomment", cint(line_start), cint(te), userdata); \ 00222 else \ 00223 callback(lang, "lblank", cint(ts), cint(te), userdata); \ 00224 } \ 00225 whole_line_comment = 0; \ 00226 line_contains_code = 0; \ 00227 line_start = 0; \ 00228 } 00229 00238 #define emb_newline(lang) { \ 00239 if (seen && seen != lang) \ 00240 std_newline(seen) \ 00241 else \ 00242 std_newline(lang) \ 00243 seen = 0; \ 00244 } 00245 00253 #define process_last_line(lang) {\ 00254 if ((whole_line_comment || line_contains_code) && callback) { \ 00255 if (line_contains_code) \ 00256 callback(lang, "lcode", cint(line_start), cint(pe), userdata); \ 00257 else if (whole_line_comment) \ 00258 callback(lang, "lcomment", cint(line_start), cint(pe), userdata); \ 00259 } \ 00260 } 00261 00270 int is_blank_entry(char **p) { 00271 char *pos = *p+1; 00272 while (*pos != '\n' && *pos != '\r' && *pos != '\f') { 00273 if (*pos != '\t' && *pos != ' ') return 0; 00274 pos++; 00275 } 00276 if (*pos == '\r' && *(pos+1) == '\n') pos++; 00277 *p = pos; 00278 return 1; 00279 } 00280 00291 #define check_blank_entry(lang) { \ 00292 if (is_blank_entry(&p)) { \ 00293 te = p + 1; \ 00294 std_newline(lang) \ 00295 } \ 00296 } 00297 00298 // Variables used by all parsers. Do not modify. 00299 00304 #define NEWLINE -1 00305 00312 #define INTERNAL_NL -2 00313 00321 #define CHECK_BLANK_ENTRY -3 00322 00324 int cs; 00325 00327 int act; 00328 00330 char *p; 00331 00333 char *pe; 00334 00336 char *eof; 00337 00339 char *ts; 00340 00342 char *te; 00343 00345 int stack[5]; 00346 00348 int top; 00349 00351 char *buffer_start; 00352 00359 #define cint(c) ((int) (c - buffer_start)) 00360 00365 int whole_line_comment; 00366 00371 int line_contains_code; 00372 00377 char *line_start; 00378 00380 int entity; 00381 00386 const char *seen; 00387 00393 int inqueue; 00394 00399 char *last_line_start; 00400 00405 int last_line_contains_code; 00406 00411 int last_whole_line_comment; 00412 00417 #define init { \ 00418 p = buffer; \ 00419 pe = buffer + length; \ 00420 eof = pe; \ 00421 \ 00422 buffer_start = buffer; \ 00423 whole_line_comment = 0; \ 00424 line_contains_code = 0; \ 00425 line_start = 0; \ 00426 entity = 0; \ 00427 seen = 0; \ 00428 inqueue = 0; \ 00429 } 00430 00431 #endif