home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / szachy / gnu / amyboard-3.2.pl2 / gamelist.c < prev    next >
C/C++ Source or Header  |  1995-05-23  |  7KB  |  291 lines

  1. /*
  2.  * gamelist.c -- Functions to manage a gamelist
  3.  * XBoard $Id: $
  4.  *
  5.  * Copyright 1995 Free Software Foundation, Inc.
  6.  *
  7.  * ------------------------------------------------------------------------
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  * ------------------------------------------------------------------------
  22.  *
  23.  * This file could well be a part of backend.c, but I prefer it this
  24.  * way.
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <errno.h>
  29. #if STDC_HEADERS
  30. # include <stdlib.h>
  31. # include <string.h>
  32. #else /* not STDC_HEADERS */
  33. # if HAVE_STRING_H
  34. #  include <string.h>
  35. # else /* not HAVE_STRING_H */
  36. #  include <strings.h>
  37. # endif /* not HAVE_STRING_H */
  38. #endif /* not STDC_HEADERS */
  39.  
  40. #include "common.h"
  41. #include "frontend.h"
  42. #include "backend.h"
  43. #include "parser.h"
  44.  
  45.  
  46. /* Variables
  47.  */
  48. List gameList;
  49.  
  50.  
  51. /* Local function prototypes
  52.  */
  53. static void GameListDeleteGame P((ListGame *));
  54. static ListGame *GameListCreate P((void));
  55. static void GameListFree P((List *));
  56.  
  57.  
  58. /* Delete a ListGame; implies removint it from a list.
  59.  */
  60. static void GameListDeleteGame(listGame)
  61.     ListGame *listGame;
  62. {
  63.     if (listGame) {
  64.     if (listGame->gameInfo.event) free(listGame->gameInfo.event);
  65.     if (listGame->gameInfo.site) free(listGame->gameInfo.site);
  66.     if (listGame->gameInfo.date) free(listGame->gameInfo.date);
  67.     if (listGame->gameInfo.round) free(listGame->gameInfo.round);
  68.     if (listGame->gameInfo.white) free(listGame->gameInfo.white);
  69.     if (listGame->gameInfo.black) free(listGame->gameInfo.black);
  70.     if (listGame->gameInfo.fen) free(listGame->gameInfo.fen);
  71.     if (listGame->gameInfo.resultDetails) free(listGame->gameInfo.resultDetails);
  72.     if (listGame->gameInfo.timeControl) free(listGame->gameInfo.timeControl);
  73.     if (listGame->gameInfo.extraTags) free(listGame->gameInfo.extraTags);
  74.     ListNodeFree((ListNode *) listGame);
  75.     }
  76. }
  77.  
  78.  
  79. /* Free the previous list of games.
  80.  */
  81. static void GameListFree(gameList)
  82.     List *gameList;
  83. {
  84.     while (!ListEmpty(gameList))
  85.     {
  86.     GameListDeleteGame((ListGame *) gameList->head);
  87.     }
  88. }
  89.  
  90.  
  91.  
  92. /* Initialize a new GameInfo structure.
  93.  */
  94. void GameListInitGameInfo(gameInfo)
  95.     GameInfo *gameInfo;
  96. {
  97.     gameInfo->event = NULL;
  98.     gameInfo->site = NULL;
  99.     gameInfo->date = NULL;
  100.     gameInfo->round = NULL;
  101.     gameInfo->white = NULL;
  102.     gameInfo->black = NULL;
  103.     gameInfo->result = GameUnfinished;
  104.     gameInfo->fen = NULL;
  105.     gameInfo->resultDetails = NULL;
  106.     gameInfo->timeControl = NULL;
  107.     gameInfo->extraTags = NULL;
  108. }
  109.  
  110.  
  111. /* Create empty ListGame; returns ListGame or NULL, if out of memory.
  112.  *
  113.  * Note, that the ListGame is *not* added to any list
  114.  */
  115. static ListGame *GameListCreate()
  116.  
  117. {
  118.     ListGame *listGame;
  119.  
  120.     if ((listGame = (ListGame *) ListNodeCreate(sizeof(*listGame)))) {
  121.     GameListInitGameInfo(&listGame->gameInfo);
  122.     }
  123.     return(listGame);
  124. }
  125.  
  126.  
  127. /* Creates a new game for the gamelist.
  128.  */
  129. static int GameListNewGame(ListGame **listGamePtr)
  130.  
  131. {
  132.     if (!(*listGamePtr = (ListGame *) GameListCreate())) {
  133.     GameListFree(&gameList);
  134.     return(ENOMEM);
  135.     }
  136.     ListAddTail(&gameList, (ListNode *) *listGamePtr);
  137.     return(0);
  138. }
  139.  
  140.  
  141. /* Build the list of games in the open file f.
  142.  * Returns 0 for success or error number.
  143.  */
  144. int GameListBuild(f)
  145.     FILE *f;
  146. {
  147.     ChessMove cm, lastStart;
  148.     int gameNumber;
  149.     ListGame *currentListGame = NULL;
  150.     int error;
  151.     int offset;
  152.  
  153.     GameListFree(&gameList);
  154.     yynewfile(f);
  155.     gameNumber = 0;
  156.  
  157.     lastStart = (ChessMove) 0;
  158.     do {
  159.     yyboardindex = 1;
  160.     offset = yyoffset();
  161.     cm = (ChessMove) yylex();
  162.     switch (cm) {
  163.         case GNUChessGame:
  164.         case XBoardGame:
  165.         lastStart = cm;
  166.         break;
  167.         case MoveNumberOne:
  168.         switch (lastStart) {
  169.             case GNUChessGame:
  170.             break;  /*  ignore  */
  171.             case XBoardGame:
  172.             case PGNTag:
  173.             lastStart = cm;
  174.             break;  /*  Already counted */
  175.             case (ChessMove) 0:
  176.             case MoveNumberOne:
  177.             if ((error = GameListNewGame(¤tListGame))) {
  178.                 return(error);
  179.             }
  180.             currentListGame->number = ++gameNumber;
  181.             currentListGame->offset = offset;
  182.             lastStart = cm;
  183.             break;
  184.             default:
  185.             break;  /*  impossible  */
  186.         }
  187.         break;
  188.         case PGNTag:
  189.         switch (lastStart) {
  190.             case GNUChessGame:
  191.             case PGNTag:
  192.             case MoveNumberOne:
  193.             case (ChessMove) 0:
  194.             if ((error = GameListNewGame(¤tListGame))) {
  195.                 return(error);
  196.             }
  197.             currentListGame->number = ++gameNumber;
  198.             currentListGame->offset = offset;
  199.             lastStart = cm;
  200.             break;
  201.             case XBoardGame:
  202.             lastStart = cm;
  203.             break;  /*  Already counted */
  204.             default:
  205.             break;  /*  impossible  */
  206.         }
  207.         ParsePGNTag(yy_text, ¤tListGame->gameInfo);
  208.         do {
  209.             yyboardindex = 1;
  210.             offset = yyoffset();
  211.             cm = (ChessMove) yylex();
  212.             if (cm == PGNTag) {
  213.             ParsePGNTag(yy_text, ¤tListGame->gameInfo);
  214.             }
  215.         } while (cm == PGNTag  ||  cm == Comment);
  216.         break;
  217.         default:
  218.         break;
  219.     }
  220.     }
  221.     while (cm != (ChessMove) 0);
  222.  
  223.  
  224.     /* Scan gamelist and add missing event, white and black fields,
  225.      * so that the list can be displayed.
  226.      */
  227.     for (currentListGame = (ListGame *) gameList.head;
  228.      currentListGame->node.succ;
  229.      currentListGame = (ListGame *) currentListGame->node.succ) {
  230.     if (!currentListGame->gameInfo.event  &&
  231.         !StrSavePtr("Unknown", ¤tListGame->gameInfo.event)) {
  232.         return(ENOMEM);
  233.     }
  234.     if (!currentListGame->gameInfo.white  &&
  235.         !StrSavePtr("Unknown", ¤tListGame->gameInfo.white)) {
  236.         return(ENOMEM);
  237.     }
  238.     if (!currentListGame->gameInfo.black  &&
  239.         !StrSavePtr("Unknown", ¤tListGame->gameInfo.black)) {
  240.         return(ENOMEM);
  241.     }
  242.     if (appData.debugMode) {
  243.         fprintf(debugFP, "Parsed game number %d, offset %ld:\n",
  244.             currentListGame->number, currentListGame->offset);
  245.         PrintPGNTags(debugFP, ¤tListGame->gameInfo);
  246.     }
  247.     }
  248.  
  249.     return(0);
  250. }
  251.  
  252.  
  253. /* Clear an existing GameInfo structure.
  254.  */
  255. void ClearGameInfo(gameInfo)
  256.     GameInfo *gameInfo;
  257. {
  258.     if (gameInfo->event != NULL) {
  259.     free(gameInfo->event);
  260.     }
  261.     if (gameInfo->site != NULL) {
  262.     free(gameInfo->site);
  263.     }
  264.     if (gameInfo->date != NULL) {
  265.     free(gameInfo->date);
  266.     }
  267.     if (gameInfo->round != NULL) {
  268.     free(gameInfo->round);
  269.     }
  270.     if (gameInfo->white != NULL) {
  271.     free(gameInfo->white);
  272.     }
  273.     if (gameInfo->black != NULL) {
  274.     free(gameInfo->black);
  275.     }
  276.     if (gameInfo->resultDetails != NULL) {
  277.     free(gameInfo->resultDetails);
  278.     }
  279.     if (gameInfo->fen != NULL) {
  280.     free(gameInfo->fen);
  281.     }
  282.     if (gameInfo->timeControl != NULL) {
  283.     free(gameInfo->timeControl);
  284.     }
  285.     if (gameInfo->extraTags != NULL) {
  286.     free(gameInfo->extraTags);
  287.     }
  288.  
  289.     GameListInitGameInfo(gameInfo);
  290. }
  291.