/* Core Wars. * Copyright (C) 1999 Walter Hofmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 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. */ #include #include #include #include #include #include #ifndef CMD_LINE #include #endif #include "main.h" #include "main-gui.h" #include "parser-cw.h" #include "program.h" #include "program-cw.h" #include "program-rc.h" #include "options.h" #include "select.h" #include "execute.h" struct program *program_list_root; /* Unloads error and code from struct program. */ void unload_program (struct program *p) { if (p->error) { free (p->error); p->error = NULL; } if (p->title) { free (p->title); p->title = NULL; } if (p->author) { free (p->author); p->author = NULL; } if (p->language==LANGUAGE_CW) cw_free_program (p); else if (p->language==LANGUAGE_RC) rc_free_program (p); } /* Frees struct program. Unloads error and code if neccessary. Frees other allocated fields. Assumes filename is allocated. */ void unlink_and_free_program (struct program *p) { unload_program (p); free (p->filename); if (p->prev) p->prev->next = p->next; if (p->next) p->next->prev = p->prev; if (p==program_list_root) program_list_root = p->next; free (p); } /* Allocates struct program and links it in doubly linked list. Initialises error and code to NULL. Returns pointer to struct program. */ struct program *alloc_and_link_program () { struct program *p; p = malloc (sizeof (struct program)); p->next = program_list_root; p->prev = NULL; if (program_list_root) program_list_root->prev = p; program_list_root = p; p->error = NULL; p->title = NULL; p->author = NULL; p->language = LANGUAGE_NONE; p->load_count = STANDARD_LOAD_COUNT; p->tournament_count = 0; p->tournament_score = 0; p->tournament_games = 0; return p; } #ifndef CMD_LINE /* Checks each loaded program for deletions and changes in the source code. Reloads if neccessary. Old entries are removed. Must only be called when not running! */ void recheck_program_list () { struct program *p = program_list_root, *next; struct stat buf; bool remove; execute_cleanup (); while (p) { remove = TRUE; if (!stat (p->filename, &buf)) if (S_ISREG (buf.st_mode)) { if (p->inode==buf.st_ino && p->device==buf.st_dev && p->mtime>=buf.st_mtime) remove = FALSE; else { if ((p->language==LANGUAGE_CW && cw_load_program (p)==OK) || (p->language==LANGUAGE_RC && rc_load_program (p)==OK)) { p->inode = buf.st_ino; p->device = buf.st_dev; p->mtime = buf.st_mtime; remove = FALSE; } } } next = p->next; if (remove) unlink_and_free_program (p); p = next; } select_update_list (); } int add_program_directory(const char *directory) { DIR *dir; struct dirent *entry; int d_len, fn_len; char filename[1024]; struct stat buf; struct program *p; d_len = strlen (directory); dir = opendir (directory); if (!dir) { perror ("opendir"); return FAIL; } while ((entry = readdir (dir))!=NULL) { fn_len = strlen (entry->d_name); if ((fn_len>CW_PROGRAM_FILE_EXTENSION_LENGTH && strcmp (entry->d_name+fn_len-CW_PROGRAM_FILE_EXTENSION_LENGTH, CW_PROGRAM_FILE_EXTENSION)==0) || (fn_len>RC_PROGRAM_FILE_EXTENSION_LENGTH && strcmp (entry->d_name+fn_len-RC_PROGRAM_FILE_EXTENSION_LENGTH, RC_PROGRAM_FILE_EXTENSION)==0)) { strcpy (filename, directory); strcat (filename, "/"); strcat (filename, entry->d_name); if (stat (filename, &buf)) perror ("stat"); else if (S_ISREG (buf.st_mode)) { p = program_list_root; while (p) { if (p->inode==buf.st_ino && p->device==buf.st_dev) break; p = p->next; } if (!p) { p = alloc_and_link_program (); p->filename = malloc (fn_len+1+d_len+1); strcpy (p->filename, filename); p->device = buf.st_dev; p->inode = buf.st_ino; p->mtime = buf.st_mtime; if (strcmp (entry->d_name+fn_len-CW_PROGRAM_FILE_EXTENSION_LENGTH, CW_PROGRAM_FILE_EXTENSION)==0) { p->language = LANGUAGE_CW; p->lang.cw.code = NULL; } else { p->language = LANGUAGE_RC; p->lang.rc.obj = NULL; } if ((p->language==LANGUAGE_CW && cw_load_program (p)==FAIL) || (p->language==LANGUAGE_RC && rc_load_program (p)==FAIL)) unlink_and_free_program (p); } } } } closedir (dir); select_update_list (); return OK; } void program_update () { struct program *p, *p2; p = program_list_root; while (p) { p2 = p->next; unload_program (p); if ((p->language==LANGUAGE_RC && rc_load_program (p)==FAIL) || (p->language==LANGUAGE_CW && cw_load_program (p)==FAIL)) unlink_and_free_program (p); p = p2; } } #endif