/****************************************************************************** * TinTin++ * * Copyright (C) 2004 (See CREDITS file) * * * * This program is protected under the GNU GPL (See COPYING) * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ******************************************************************************/ /****************************************************************************** * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t * * * * coded by Peter Unold 1992 * ******************************************************************************/ #include "tintin.h" #include <sys/stat.h> /* read and execute a command file, supports multi lines - Igor */ DO_COMMAND(do_read) { FILE *fp; struct stat filedata; char *bufi, *bufo, filename[BUFFER_SIZE], temp[BUFFER_SIZE], *pti, *pto, last = 0; int lvl, cnt, com, lnc, fix, ok; int counter[LIST_MAX]; get_arg_in_braces(arg, filename, TRUE); substitute(ses, filename, filename, SUB_VAR|SUB_FUN); if ((fp = fopen(filename, "r")) == NULL) { tintin_printf(ses, "#READ {%s} - FILE NOT FOUND.", filename); return ses; } temp[0] = getc(fp); if (!isgraph((int) temp[0]) || isalpha((int) temp[0])) { tintin_printf(ses, "#ERROR: #READ {%s} - INVALID START OF FILE.", filename); fclose(fp); return ses; } ungetc(temp[0], fp); for (cnt = 0 ; cnt < LIST_MAX ; cnt++) { if (HAS_BIT(list_table[cnt].flags, LIST_FLAG_READ)) { counter[cnt] = ses->list[cnt]->used; } } stat(filename, &filedata); if ((bufi = (char *) calloc(1, filedata.st_size + 2)) == NULL || (bufo = (char *) calloc(1, filedata.st_size + 2)) == NULL) { tintin_printf(ses, "#ERROR: #READ {%s} - FAILED TO ALLOCATE MEMORY.", filename); fclose(fp); return ses; } fread(bufi, 1, filedata.st_size, fp); pti = bufi; pto = bufo; lvl = com = lnc = fix = ok = 0; while (*pti) { if (com == 0) { #ifdef BIG5 if (*pti & 0x80) { *pto++ = *pti++; if (*pti) { *pto++ = *pti++; } continue; } #endif switch (*pti) { case DEFAULT_OPEN: *pto++ = *pti++; lvl++; last = DEFAULT_OPEN; break; case DEFAULT_CLOSE: *pto++ = *pti++; lvl--; last = DEFAULT_CLOSE; break; case COMMAND_SEPARATOR: *pto++ = *pti++; last = COMMAND_SEPARATOR; break; case ' ': *pto++ = *pti++; break; case '/': if (lvl == 0 && pti[1] == '*') { pti += 2; com += 1; } else { *pto++ = *pti++; } break; case '\t': *pto++ = *pti++; break; case '\r': pti++; break; case '\n': lnc++; pto--; while (isspace((int) *pto)) { pto--; } pto++; if (fix == 0 && pti[1] == gtd->tintin_char) { if (lvl == 0) { ok = lnc + 1; } else { fix = lnc; } } if (lvl) { pti++; while (isspace((int) *pti)) { if (*pti == '\n') { lnc++; if (fix == 0 && pti[1] == gtd->tintin_char) { fix = lnc; } } pti++; } if (*pti != DEFAULT_CLOSE && last == 0) { *pto++ = ' '; } } else for (cnt = 1 ; ; cnt++) { if (pti[cnt] == 0) { *pto++ = *pti++; break; } if (pti[cnt] == DEFAULT_OPEN) { pti++; while (isspace((int) *pti)) { pti++; } *pto++ = ' '; break; } if (!isspace((int) pti[cnt])) { *pto++ = *pti++; break; } } break; default: *pto++ = *pti++; last = 0; break; } } else { switch (*pti) { case '/': if (pti[1] == '*') { pti += 2; com += 1; } else { pti += 1; } break; case '*': if (pti[1] == '/') { pti += 2; com -= 1; } else { pti += 1; } break; case '\n': lnc++; pti++; break; default: pti++; break; } } } *pto++ = '\n'; *pto = '\0'; if (lvl) { tintin_printf(ses, "#ERROR: #READ {%s} - MISSING %d '%c' BETWEEN LINE %d AND %d.", filename, abs(lvl), lvl < 0 ? DEFAULT_OPEN : DEFAULT_CLOSE, fix == 0 ? 1 : ok, fix == 0 ? lnc + 1 : fix); fclose(fp); free(bufi); free(bufo); return ses; } if (com) { tintin_printf(ses, "#ERROR: #READ {%s} - MISSING %d '%s'", filename, abs(com), com < 0 ? "/*" : "*/"); fclose(fp); free(bufi); free(bufo); return ses; } sprintf(temp, "{TINTIN CHAR} {%c}", bufo[0]); gtd->quiet++; do_configure(ses, temp); lvl = 0; pti = bufo; pto = bufi; while (*pti) { if (*pti != '\n') { *pto++ = *pti++; continue; } *pto = 0; if (strlen(bufi) >= BUFFER_SIZE) { gtd->quiet--; bufi[20] = 0; tintin_printf(ses, "#ERROR: #READ {%s} - BUFFER OVERFLOW AT COMMAND: %s.", filename, bufi); fclose(fp); free(bufi); free(bufo); return ses; } if (bufi[0]) { ses = script_driver(ses, -1, bufi); } pto = bufi; pti++; } gtd->quiet--; if (!HAS_BIT(ses->flags, SES_FLAG_VERBOSE)) { for (cnt = 0 ; cnt < LIST_MAX ; cnt++) { if (HAS_BIT(list_table[cnt].flags, LIST_FLAG_READ)) { switch (ses->list[cnt]->used - counter[cnt]) { case 0: break; case 1: show_message(ses, LIST_MESSAGE, "#OK: %3d %s LOADED.", ses->list[cnt]->used - counter[cnt], list_table[cnt].name); break; default: show_message(ses, LIST_MESSAGE, "#OK: %3d %s LOADED.", ses->list[cnt]->used - counter[cnt], list_table[cnt].name_multi); break; } } } } fclose(fp); free(bufi); free(bufo); return ses; } DO_COMMAND(do_write) { FILE *file; char filename[BUFFER_SIZE]; struct listroot *root; int i, j, cnt = 0; get_arg_in_braces(arg, filename, TRUE); if (*filename == 0 || (file = fopen(filename, "w")) == NULL) { tintin_printf(ses, "#ERROR: #WRITE: COULDN'T OPEN {%s} TO WRITE.", filename); return ses; } for (i = 0 ; i < LIST_MAX ; i++) { root = ses->list[i]; if (!HAS_BIT(root->flags, LIST_FLAG_WRITE)) { continue; } for (j = 0 ; j < root->used ; j++) { if (*root->list[j]->group == 0) { write_node(ses, i, root->list[j], file); cnt++; } } } fclose(file); show_message(ses, LIST_MESSAGE, "#WRITE: %d COMMANDS WRITTEN TO {%s}.", cnt, filename); return ses; } void write_node(struct session *ses, int list, struct listnode *node, FILE *file) { char result[STRING_SIZE], buffer[BUFFER_SIZE]; int llen = UMAX(20, strlen(node->left)); int rlen = UMAX(25, strlen(node->right)); push_call("write_node(%d,%p,%p)",list,node,file); switch (list) { case LIST_EVENT: case LIST_FUNCTION: case LIST_MACRO: sprintf(result, "%c%s {%s}\n{\n%s\n}\n\n", gtd->tintin_char, list_table[list].name, node->left, script_writer(ses, node->right)); break; case LIST_ACTION: case LIST_ALIAS: sprintf(result, "%c%s {%s}\n{\n%s\n}\n{%s}\n\n", gtd->tintin_char, list_table[list].name, node->left, script_writer(ses, node->right), node->pr); break; case LIST_VARIABLE: show_nest_node(node, buffer, 1); sprintf(result, "%c%-16s {%s} %*s {%s}\n", gtd->tintin_char, list_table[list].name, node->left, 20 - llen, "", buffer); break; default: switch (list_table[list].args) { case 0: result[0] = 0; break; case 1: sprintf(result, "%c%-16s {%s}\n", gtd->tintin_char, list_table[list].name, node->left); break; case 2: sprintf(result, "%c%-16s {%s} %*s {%s}\n", gtd->tintin_char, list_table[list].name, node->left, 20 - llen, "", node->right); break; case 3: sprintf(result, "%c%-16s {%s} %*s {%s} %*s {%s}\n", gtd->tintin_char, list_table[list].name, node->left, 20 - llen, "", node->right, 25 - rlen, "", node->pr); break; } break; } fputs(result, file); pop_call(); return; }