TToken* get_token() { if(token_buffer != NULL) { token = token_buffer; token_buffer = NULL; return token; } TString buffer; States state = S_START; char a[2]; // array for hex number int c, i=0; initString(&buffer, STR_DEFAULT_SIZE); token->data = buffer.data; while(1) { c = fgetc(fp); switch(state) { case S_START: switch (c) { case EOF: token->type = TOKEN_EOF; return token; case '+': token->type = TOKEN_ADD; return token; case '-': token->type = TOKEN_SUB; return token; case '*': token->type = TOKEN_MUL; return token; case '/': state = S_DIV; break; case '=': state = S_ASSIGN; break; case '!': state = S_EXCM; break; case '<': state = S_LESS; break; case '>': state = S_GREAT; break; case '(': token->type = TOKEN_LROUND_BRACKET; return token; case ')': token->type = TOKEN_RROUND_BRACKET; return token; case '{': token->type = TOKEN_LCURLY_BRACKET; return token; case '}': token->type = TOKEN_RCURLY_BRACKET; return token; case ',': token->type = TOKEN_COMMA; return token; case ';': token->type = TOKEN_SEMICOLON; return token; case '"': state = S_QUOT; break; default: if(isdigit(c)) { state = S_INT; insertIntoString(&buffer, c); } else if (isalpha(c) || c == '_') { state = S_IDENT; insertIntoString(&buffer, c); } else if (isspace(c)) break; else state = S_ERROR; } break; //********************************************** case S_INT: // INTEGER if (isdigit(c)) { insertIntoString(&buffer, c); } else if(c == '.') { insertIntoString(&buffer, c); state = S_DOT; } else if(c == 'E' || c == 'e') { insertIntoString(&buffer, c); state = S_EXPO_E; } else { insertIntoString(&buffer, 0); ungetc(c,fp); token->type = TOKEN_INT_VALUE; token->data = buffer.data; return token; } break; //************************************************* case S_DOT: // number DOT if (isdigit(c)) { insertIntoString(&buffer, c); state = S_DBL; } else { state = S_ERROR; } break; //************************************************* case S_DBL: // DOUBLE if (isdigit(c)) { insertIntoString(&buffer, c); } else if(c == 'E' || c == 'e') { insertIntoString(&buffer, c); state = S_EXPO_E; } else { insertIntoString(&buffer, 0); ungetc(c,fp); token->type = TOKEN_DOUBLE_VALUE; token->data = buffer.data; return token; } break; //****************************************************** case S_EXPO_E: // state S_EXPO_E if (isdigit(c)) { insertIntoString(&buffer, c); state = S_EXPO; } else if (c == '+' || c == '-') { insertIntoString(&buffer, c); state= S_EXPO_M; } else { state = S_ERROR; } break; //***************************************************** case S_EXPO_M: // state S_EXPO_M if (isdigit(c)) { insertIntoString(&buffer, c); state= S_EXPO; } else { state=S_ERROR; } break; //***************************************************** case S_EXPO: // state S_EXPO if (isdigit(c)) insertIntoString(&buffer, c); else { insertIntoString(&buffer, 0); ungetc(c,fp); token->type = TOKEN_DOUBLE_VALUE; token->data = buffer.data; return token; } break; //*************************************************** case S_IDENT: //STATE IDENTIFIER if (isalnum(c) || c == '_') { insertIntoString(&buffer, c); } else { insertIntoString(&buffer, 0); token->type = TOKEN_IDENTIFIER; token->data = buffer.data; keyword_check(); ungetc(c,fp); return token; } break; //************************************************************* case S_DIV: // DIVIDE if (c == '/') state = S_LCOM; else if (c == '*') state = S_LBC; else { ungetc(c,fp); token->type = TOKEN_DIV; return token; } break; //*************************************************** case S_LCOM: // LINE COMMENT if (c == '\n') state = S_START; break; //**************************************************** case S_LBC: // LEFT BLOCK COMMENT if (c == '*') state = S_RBC; if(c == EOF) state = S_ERROR; break; //**************************************************** case S_RBC: //RIGHT BLOCK COMMENT if (c == '/') state = S_START; else if (c == EOF) state = S_ERROR; else if (c == '*'); else state = S_LBC; break; //**************************************************** case S_ASSIGN: // ASSIGNMENT if (c == '=') { token->type = TOKEN_EQUAL; return token; } else { ungetc(c,fp); token->type = TOKEN_ASSIGN; return token; } break; //**************************************************** case S_EXCM: // EXCLAMATION MARK if (c == '=') { token->type = TOKEN_NOT_EQUAL; return token; } else state = S_ERROR; break; //**************************************************** case S_LESS: // LESS THAN if (c=='=') { token->type=TOKEN_LESS_EQUAL; return token; } else if (c == '<') { token->type=TOKEN_COUT_BRACKET; return token; } else { ungetc(c,fp); token->type = TOKEN_LESS; return token; } break; //**************************************************** case S_GREAT: //GREATER THAN if (c=='=') { token->type = TOKEN_GREATER_EQUAL; return token; } else if (c == '>') { token->type = TOKEN_CIN_BRACKET; return token; } else { ungetc(c,fp); token->type = TOKEN_GREATER; return token; } break; //**************************************************** case S_QUOT: //QUOTATION if (c == '"') { insertIntoString(&buffer, 0); token->type = TOKEN_STRING_VALUE; token->data = buffer.data; return token; } else if(c == EOF) { state = S_ERROR; } else if(c == '\\') { state = S_ESCAPE; } else if(c > 31) { insertIntoString(&buffer, c); } else state = S_ERROR; break; //**************************************************** case S_ESCAPE: //ESCAPE SEQUENCES if (c == 't') { insertIntoString(&buffer, '\t'); state = S_QUOT; } else if (c == '"') { insertIntoString(&buffer, '"'); state = S_QUOT; } else if (c == '\\') { insertIntoString(&buffer, '\\'); state = S_QUOT; } else if (c == 'n') { insertIntoString(&buffer, '\n'); state = S_QUOT; } else if (c == 'x') { state = S_HEX_NUMBER; } else { state=S_ERROR; } break; //**************************************************** case S_HEX_NUMBER: // HEXADECIMAL NUMBER if (isxdigit(c) && (i < 2)) // if is hexadigit and i<2 { a[i]=c; i++; if (i == 2) { if ((a[0] == '0') && (a[1] == '0')) state=S_ERROR; else { char hta = hex_to_ascii(a[0], a[1]); insertIntoString(&buffer, hta); state = S_QUOT; i = 0; } } } else { state=S_ERROR; } break; //**************************************************** case S_ERROR: // ERROR exit_error(E_LEX); } } }
/*---------------------------------------------------------------------- Function to control flag set/clearing Basically, turn the flags into a fake list of features... Returns 0 unless user has added a keyword, then 1. ----*/ int flag_maintenance_screen(struct pine *ps, struct flag_screen *flags) { int i, lv, lc, maxwidth, offset, need, rv = 0; char tmp[1200], **p, *spacer; CONF_S *ctmpa, *first_line; struct flag_table *fp; OPT_SCREEN_S screen; try_again: maxwidth = MAX(MIN((ps->ttyo ? ps->ttyo->screen_cols : 80), 150), 30); first_line = NULL; ctmpa = NULL; for(p = flags->explanation; p && *p; p++) { new_confline(&ctmpa); ctmpa->keymenu = &flag_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = flag_checkbox_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 0; ctmpa->value = cpystr(_(*p)); } /* Now wire flags checkboxes together */ for(lv = 0, lc = 0, fp = (flags->flag_table ? *flags->flag_table : NULL); fp && fp->name; fp++) { /* longest name */ if(fp->flag != F_COMMENT) { if(lv < (i = utf8_width(_(fp->name)))) lv = i; if(fp->comment && lc < (i = utf8_width(fp->comment))) lc = i; } } lv = MIN(lv,100); lc = MIN(lc,100); if(lc > 0) spacer = " "; else spacer = ""; offset = 6; if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth) { offset -= (need - maxwidth); offset = MAX(0,offset); if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth) { spacer = " "; if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth) { lc -= (need - maxwidth); lc = MAX(0,lc); if(lc == 0) spacer = ""; } } } new_confline(&ctmpa); ctmpa->keymenu = &flag_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = flag_checkbox_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 0; ctmpa->value = cpystr(""); new_confline(&ctmpa); ctmpa->keymenu = &flag_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = flag_checkbox_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 0; utf8_snprintf(tmp, sizeof(tmp), "%*.*w %s", offset+3, offset+3, _("Set"), _("Flag/Keyword Name")); tmp[sizeof(tmp)-1] = '\0'; ctmpa->value = cpystr(tmp); new_confline(&ctmpa); ctmpa->keymenu = &flag_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = flag_checkbox_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 0; snprintf(tmp, sizeof(tmp), "%*.*s--- %.*s", offset, offset, "", lv+lc+strlen(spacer), repeat_char(lv+lc+strlen(spacer), '-')); tmp[sizeof(tmp)-1] = '\0'; ctmpa->value = cpystr(tmp); for(fp = (flags->flag_table ? *flags->flag_table : NULL); fp && fp->name; fp++) { /* build the list */ new_confline(&ctmpa); if(!first_line && (fp->flag != F_COMMENT)) first_line = ctmpa; ctmpa->keymenu = &flag_keymenu; ctmpa->tool = flag_checkbox_tool; ctmpa->valoffset = offset; if(fp->flag == F_COMMENT) { ctmpa->help = NO_HELP; ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr(fp->name); } else { ctmpa->help = fp->help; ctmpa->d.f.ftbl = flags->flag_table; ctmpa->d.f.fp = fp; utf8_snprintf(tmp, sizeof(tmp), "[%c] %-*.*w%s%-*.*w", (fp->set == 0) ? ' ' : (fp->set == 1) ? 'X' : '?', lv, lv, _(fp->name), spacer, lc, lc, fp->comment ? fp->comment : ""); ctmpa->value = cpystr(tmp); } } memset(&screen, 0, sizeof(screen)); /* * TRANSLATORS: FLAG MAINTENANCE is a screen title. * Print something1 using something2. configuration is something1 */ if(conf_scroll_screen(ps, &screen, first_line, _("FLAG MAINTENANCE"), _("configuration"), 0) == FLAG_ADD_RETURN) { int flags, r; char keyword[500]; char nickname[500]; char prompt[500]; char *error = NULL; KEYWORD_S *kw; HelpType help; /* * User is asking to add a new keyword. We will add it to the * mailbox if necessary and add it to the keywords list from * Setup/Config. Then we will modify the flag_table and present * the flag modification screen again. */ ps->mangled_screen = 1; keyword[0] = '\0'; flags = OE_APPEND_CURRENT; help = NO_HELP; do { if(error) { q_status_message(SM_ORDER, 3, 4, error); fs_give((void **) &error); } strncpy(prompt, _("Keyword to be added : "), sizeof(prompt)-1); prompt[sizeof(prompt)-1] = '\0'; r = optionally_enter(keyword, -FOOTER_ROWS(ps_global), 0, sizeof(keyword), prompt, NULL, help, &flags); if(r == 3) help = help == NO_HELP ? h_type_keyword : NO_HELP; else if(r == 1) { cmd_cancelled("Add Keyword"); goto try_again; } removing_leading_and_trailing_white_space(keyword); } while(r == 3 || keyword_check(keyword, &error)); for(kw = ps->keywords; kw; kw = kw->next) { if(kw->kw && !strucmp(kw->kw, keyword)) { q_status_message(SM_ORDER, 3, 4, _("Keyword already configured, changing nickname")); break; } } snprintf(prompt, sizeof(prompt), _("Optional nickname for \"%s\" : "), keyword); nickname[0] = '\0'; help = NO_HELP; do { r = optionally_enter(nickname, -FOOTER_ROWS(ps_global), 0, sizeof(nickname), prompt, NULL, help, &flags); if(r == 3) help = help == NO_HELP ? h_type_keyword_nickname : NO_HELP; else if(r == 1) { cmd_cancelled("Add Keyword"); goto try_again; } removing_leading_and_trailing_white_space(nickname); } while(r == 3); if(keyword[0]) { char ***alval; int offset = -1; struct variable *var; var = &ps_global->vars[V_KEYWORDS]; alval = ALVAL(var, Main); for(kw = ps->keywords; kw; kw = kw->next) { offset++; if(kw->kw && !strucmp(kw->kw, keyword)) { /* looks like it should already exist at offset */ break; } } if(!kw) offset = -1; if(offset >= 0 && (*alval) && (*alval)[offset]) { fs_give((void **) &(*alval)[offset]); (*alval)[offset] = put_pair(nickname, keyword); } else if(!*alval) { offset = 0; *alval = (char **) fs_get(2*sizeof(char *)); (*alval)[offset] = put_pair(nickname, keyword); (*alval)[offset+1] = NULL; } else { for(offset=0; (*alval)[offset]; offset++); ; fs_resize((void **) alval, (offset + 2) * sizeof(char *)); (*alval)[offset] = put_pair(nickname, keyword); (*alval)[offset+1] = NULL; } set_current_val(var, TRUE, FALSE); if(ps_global->prc) ps_global->prc->outstanding_pinerc_changes = 1; if(ps_global->keywords) free_keyword_list(&ps_global->keywords); if(var->current_val.l && var->current_val.l[0]) ps_global->keywords = init_keyword_list(var->current_val.l); clear_index_cache(ps_global->mail_stream, 0); rv = 1; } } ps->mangled_screen = 1; return(rv); }