# HG changeset patch # User Mike Becker # Date 1720721121 -7200 # Node ID 0f1c55d2a90a5faba89756e99155a3f7ab2d8dfe # Parent 07a3743ce6ac19d7cb678b51138d6c6fe2bf3d39 hotfix: ampersand not escaped in html output diff -r 07a3743ce6ac -r 0f1c55d2a90a src/highlighter.c --- a/src/highlighter.c Thu Jul 11 19:41:06 2024 +0200 +++ b/src/highlighter.c Thu Jul 11 20:05:21 2024 +0200 @@ -40,6 +40,8 @@ cxBufferPutString(dest, ">"); } else if (c == '<') { cxBufferPutString(dest, "<"); + } else if (c == '&') { + cxBufferPutString(dest, "&"); } else if (c) { cxBufferPut(dest, c); } diff -r 07a3743ce6ac -r 0f1c55d2a90a test/gs/bigtest.html --- a/test/gs/bigtest.html Thu Jul 11 19:41:06 2024 +0200 +++ b/test/gs/bigtest.html Thu Jul 11 20:05:21 2024 +0200 @@ -131,7 +131,7 @@ 78 memset(string, 0, 8); 79 80 /* special formats for castling */ - 81 if ((move->piece&PIECE_MASK) == KING && + 81 if ((move->piece&PIECE_MASK) == KING && 82 abs(move->tofile-move->fromfile) == 2) { 83 if (move->tofile==fileidx('c')) { 84 memcpy(string, "O-O-O", 5); @@ -145,7 +145,7 @@ 92 int idx = string[0] ? 1 : 0; 93 94 /* find out how many source information we do need */ - 95 uint8_t piece = move->piece & PIECE_MASK; + 95 uint8_t piece = move->piece & PIECE_MASK; 96 if (piece == PAWN) { 97 if (move->capture) { 98 string[idx++] = filechr(move->fromfile); @@ -154,7 +154,7 @@ 101 Move threats[16]; 102 uint8_t threatcount; 103 get_real_threats(gamestate, move->torow, move->tofile, -104 move->piece&COLOR_MASK, threats, &threatcount); +104 move->piece&COLOR_MASK, threats, &threatcount); 105 if (threatcount > 1) { 106 int ambrows = 0, ambfiles = 0; 107 for (uint8_t i = 0 ; i < threatcount ; i++) { @@ -204,12 +204,12 @@ 151 elem->move = *move; 152 153 struct timeval curtimestamp; -154 gettimeofday(&curtimestamp, NULL); +154 gettimeofday(&curtimestamp, NULL); 155 elem->move.timestamp.tv_sec = curtimestamp.tv_sec; 156 elem->move.timestamp.tv_usec = curtimestamp.tv_usec; 157 158 if (gamestate->lastmove) { -159 struct movetimeval *lasttstamp = &(gamestate->lastmove->move.timestamp); +159 struct movetimeval *lasttstamp = &(gamestate->lastmove->move.timestamp); 160 uint64_t sec = curtimestamp.tv_sec - lasttstamp->tv_sec; 161 suseconds_t micros; 162 if (curtimestamp.tv_usec < lasttstamp->tv_usec) { @@ -232,7 +232,7 @@ 179 } 180 181 char getpiecechr(uint8_t piece) { -182 switch (piece & PIECE_MASK) { +182 switch (piece & PIECE_MASK) { 183 case ROOK: return 'R'; 184 case KNIGHT: return 'N'; 185 case BISHOP: return 'B'; @@ -254,25 +254,25 @@ 201 } 202 203 static void apply_move_impl(GameState *gamestate, Move *move, _Bool simulate) { -204 uint8_t piece = move->piece & PIECE_MASK; -205 uint8_t color = move->piece & COLOR_MASK; +204 uint8_t piece = move->piece & PIECE_MASK; +205 uint8_t color = move->piece & COLOR_MASK; 206 207 /* en passant capture */ -208 if (move->capture && piece == PAWN && +208 if (move->capture && piece == PAWN && 209 mdst(gamestate->board, move) == 0) { 210 gamestate->board[move->fromrow][move->tofile] = 0; 211 } 212 213 /* remove old en passant threats */ 214 for (uint8_t file = 0 ; file < 8 ; file++) { -215 gamestate->board[3][file] &= ~ENPASSANT_THREAT; -216 gamestate->board[4][file] &= ~ENPASSANT_THREAT; +215 gamestate->board[3][file] &= ~ENPASSANT_THREAT; +216 gamestate->board[4][file] &= ~ENPASSANT_THREAT; 217 } 218 219 /* add new en passant threat */ -220 if (piece == PAWN && ( -221 (move->fromrow == 1 && move->torow == 3) || -222 (move->fromrow == 6 && move->torow == 4))) { +220 if (piece == PAWN && ( +221 (move->fromrow == 1 && move->torow == 3) || +222 (move->fromrow == 6 && move->torow == 4))) { 223 move->piece |= ENPASSANT_THREAT; 224 } 225 @@ -285,7 +285,7 @@ 232 } 233 234 /* castling */ -235 if (piece == KING && move->fromfile == fileidx('e')) { +235 if (piece == KING && move->fromfile == fileidx('e')) { 236 237 if (move->tofile == fileidx('g')) { 238 gamestate->board[move->torow][fileidx('h')] = 0; @@ -316,52 +316,52 @@ 263 } 264 265 /* must move */ -266 if (move->fromfile == move->tofile && move->fromrow == move->torow) { +266 if (move->fromfile == move->tofile && move->fromrow == move->torow) { 267 return INVALID_MOVE_SYNTAX; 268 } 269 270 /* does piece exist */ -271 if ((msrc(gamestate->board, move)&(PIECE_MASK|COLOR_MASK)) -272 != (move->piece&(PIECE_MASK|COLOR_MASK))) { +271 if ((msrc(gamestate->board, move)&(PIECE_MASK|COLOR_MASK)) +272 != (move->piece&(PIECE_MASK|COLOR_MASK))) { 273 return INVALID_POSITION; 274 } 275 276 /* can't capture own pieces */ -277 if ((mdst(gamestate->board, move) & COLOR_MASK) -278 == (move->piece & COLOR_MASK)) { +277 if ((mdst(gamestate->board, move) & COLOR_MASK) +278 == (move->piece & COLOR_MASK)) { 279 return RULES_VIOLATED; 280 } 281 282 /* must capture, if and only if destination is occupied */ -283 if ((mdst(gamestate->board, move) == 0 && move->capture) || -284 (mdst(gamestate->board, move) != 0 && !move->capture)) { +283 if ((mdst(gamestate->board, move) == 0 && move->capture) || +284 (mdst(gamestate->board, move) != 0 && !move->capture)) { 285 return INVALID_MOVE_SYNTAX; 286 } 287 288 /* validate individual rules */ 289 _Bool chkrules; -290 switch (move->piece & PIECE_MASK) { +290 switch (move->piece & PIECE_MASK) { 291 case PAWN: -292 chkrules = pawn_chkrules(gamestate, move) && +292 chkrules = pawn_chkrules(gamestate, move) && 293 !pawn_isblocked(gamestate, move); 294 break; 295 case ROOK: -296 chkrules = rook_chkrules(move) && +296 chkrules = rook_chkrules(move) && 297 !rook_isblocked(gamestate, move); 298 break; 299 case KNIGHT: 300 chkrules = knight_chkrules(move); /* knight is never blocked */ 301 break; 302 case BISHOP: -303 chkrules = bishop_chkrules(move) && +303 chkrules = bishop_chkrules(move) && 304 !bishop_isblocked(gamestate, move); 305 break; 306 case QUEEN: -307 chkrules = queen_chkrules(move) && +307 chkrules = queen_chkrules(move) && 308 !queen_isblocked(gamestate, move); 309 break; 310 case KING: -311 chkrules = king_chkrules(gamestate, move) && +311 chkrules = king_chkrules(gamestate, move) && 312 !king_isblocked(gamestate, move); 313 break; 314 default: @@ -381,7 +381,7 @@ 328 } 329 330 /* find kings for check validation */ -331 uint8_t piececolor = (move->piece & COLOR_MASK); +331 uint8_t piececolor = (move->piece & COLOR_MASK); 332 333 uint8_t mykingfile = 0, mykingrow = 0, opkingfile = 0, opkingrow = 0; 334 for (uint8_t row = 0 ; row < 8 ; row++) { @@ -401,14 +401,14 @@ 348 /* simulate move for check validation */ 349 GameState simulation = gamestate_copy_sim(gamestate); 350 Move simmove = *move; -351 apply_move_impl(&simulation, &simmove, 1); +351 apply_move_impl(&simulation, &simmove, 1); 352 353 /* don't move into or stay in check position */ -354 if (is_covered(&simulation, mykingrow, mykingfile, +354 if (is_covered(&simulation, mykingrow, mykingfile, 355 opponent_color(piececolor))) { 356 -357 gamestate_cleanup(&simulation); -358 if ((move->piece & PIECE_MASK) == KING) { +357 gamestate_cleanup(&simulation); +358 if ((move->piece & PIECE_MASK) == KING) { 359 return KING_MOVES_INTO_CHECK; 360 } else { 361 /* last move is always not null in this case */ @@ -420,36 +420,36 @@ 367 /* correct check and checkmate flags (move is still valid) */ 368 Move threats[16]; 369 uint8_t threatcount; -370 move->check = get_threats(&simulation, opkingrow, opkingfile, -371 piececolor, threats, &threatcount); +370 move->check = get_threats(&simulation, opkingrow, opkingfile, +371 piececolor, threats, &threatcount); 372 373 if (move->check) { 374 /* determine possible escape fields */ 375 _Bool canescape = 0; -376 for (int dr = -1 ; dr <= 1 && !canescape ; dr++) { -377 for (int df = -1 ; df <= 1 && !canescape ; df++) { -378 if (!(dr == 0 && df == 0) && -379 isidx(opkingrow + dr) && isidx(opkingfile + df)) { +376 for (int dr = -1 ; dr <= 1 && !canescape ; dr++) { +377 for (int df = -1 ; df <= 1 && !canescape ; df++) { +378 if (!(dr == 0 && df == 0) && +379 isidx(opkingrow + dr) && isidx(opkingfile + df)) { 380 381 /* escape field neither blocked nor covered */ 382 if ((simulation.board[opkingrow + dr][opkingfile + df] -383 & COLOR_MASK) != opponent_color(piececolor)) { -384 canescape |= !is_covered(&simulation, +383 & COLOR_MASK) != opponent_color(piececolor)) { +384 canescape |= !is_covered(&simulation, 385 opkingrow + dr, opkingfile + df, piececolor); 386 } 387 } 388 } 389 } 390 /* can't escape, can he capture? */ -391 if (!canescape && threatcount == 1) { -392 canescape = is_attacked(&simulation, threats[0].fromrow, +391 if (!canescape && threatcount == 1) { +392 canescape = is_attacked(&simulation, threats[0].fromrow, 393 threats[0].fromfile, opponent_color(piececolor)); 394 } 395 396 /* can't capture, can he block? */ -397 if (!canescape && threatcount == 1) { -398 Move *threat = &(threats[0]); -399 uint8_t threatpiece = threat->piece & PIECE_MASK; +397 if (!canescape && threatcount == 1) { +398 Move *threat = &(threats[0]); +399 uint8_t threatpiece = threat->piece & PIECE_MASK; 400 401 /* knight, pawns and the king cannot be blocked */ 402 if (threatpiece == BISHOP || threatpiece == ROOK @@ -458,18 +458,18 @@ 405 /* rook aspect (on row) */ 406 int d = threat->tofile > threat->fromfile ? 1 : -1; 407 uint8_t file = threat->fromfile; -408 while (!canescape && file != threat->tofile - d) { +408 while (!canescape && file != threat->tofile - d) { 409 file += d; -410 canescape |= is_protected(&simulation, +410 canescape |= is_protected(&simulation, 411 threat->torow, file, opponent_color(piececolor)); 412 } 413 } else if (threat->fromfile == threat->tofile) { 414 /* rook aspect (on file) */ 415 int d = threat->torow > threat->fromrow ? 1 : -1; 416 uint8_t row = threat->fromrow; -417 while (!canescape && row != threat->torow - d) { +417 while (!canescape && row != threat->torow - d) { 418 row += d; -419 canescape |= is_protected(&simulation, +419 canescape |= is_protected(&simulation, 420 row, threat->tofile, opponent_color(piececolor)); 421 } 422 } else { @@ -479,11 +479,11 @@ 426 427 uint8_t row = threat->fromrow; 428 uint8_t file = threat->fromfile; -429 while (!canescape && file != threat->tofile - df -430 && row != threat->torow - dr) { +429 while (!canescape && file != threat->tofile - df +430 && row != threat->torow - dr) { 431 row += dr; 432 file += df; -433 canescape |= is_protected(&simulation, row, file, +433 canescape |= is_protected(&simulation, row, file, 434 opponent_color(piececolor)); 435 } 436 } @@ -495,7 +495,7 @@ 442 } 443 } 444 -445 gamestate_cleanup(&simulation); +445 gamestate_cleanup(&simulation); 446 447 return VALID_MOVE_SEMANTICS; 448 } @@ -506,9 +506,9 @@ 453 int candidatecount = 0; 454 for (uint8_t r = 0 ; r < 8 ; r++) { 455 for (uint8_t f = 0 ; f < 8 ; f++) { -456 if ((gamestate->board[r][f] & COLOR_MASK) == color) { +456 if ((gamestate->board[r][f] & COLOR_MASK) == color) { 457 // non-capturing move -458 memset(&(candidates[candidatecount]), 0, sizeof(Move)); +458 memset(&(candidates[candidatecount]), 0, sizeof(Move)); 459 candidates[candidatecount].piece = gamestate->board[r][f]; 460 candidates[candidatecount].fromrow = r; 461 candidates[candidatecount].fromfile = f; @@ -517,8 +517,8 @@ 464 candidatecount++; 465 466 // capturing move -467 memcpy(&(candidates[candidatecount]), -468 &(candidates[candidatecount-1]), sizeof(Move)); +467 memcpy(&(candidates[candidatecount]), +468 &(candidates[candidatecount-1]), sizeof(Move)); 469 candidates[candidatecount].capture = 1; 470 candidatecount++; 471 } @@ -533,10 +533,10 @@ 480 _Bool result = 0; 481 482 for (int i = 0 ; i < candidatecount ; i++) { -483 if (validate_move_rules(gamestate, &(candidates[i])) +483 if (validate_move_rules(gamestate, &(candidates[i])) 484 == VALID_MOVE_SEMANTICS) { 485 result = 1; -486 if (threats && threatcount) { +486 if (threats && threatcount) { 487 threats[(*threatcount)++] = candidates[i]; 488 } 489 } @@ -546,7 +546,7 @@ 493 } 494 495 _Bool is_pinned(GameState *gamestate, Move *move) { -496 uint8_t color = move->piece & COLOR_MASK; +496 uint8_t color = move->piece & COLOR_MASK; 497 498 uint8_t kingfile = 0, kingrow = 0; 499 for (uint8_t row = 0 ; row < 8 ; row++) { @@ -560,10 +560,10 @@ 507 508 GameState simulation = gamestate_copy_sim(gamestate); 509 Move simmove = *move; -510 apply_move(&simulation, &simmove); -511 _Bool covered = is_covered(&simulation, +510 apply_move(&simulation, &simmove); +511 _Bool covered = is_covered(&simulation, 512 kingrow, kingfile, opponent_color(color)); -513 gamestate_cleanup(&simulation); +513 gamestate_cleanup(&simulation); 514 515 return covered; 516 } @@ -577,7 +577,7 @@ 524 525 Move candidates[16]; 526 uint8_t candidatecount; -527 if (get_threats(gamestate, row, file, color, candidates, &candidatecount)) { +527 if (get_threats(gamestate, row, file, color, candidates, &candidatecount)) { 528 529 _Bool result = 0; 530 uint8_t kingfile = 0, kingrow = 0; @@ -593,11 +593,11 @@ 540 for (uint8_t i = 0 ; i < candidatecount ; i++) { 541 GameState simulation = gamestate_copy_sim(gamestate); 542 Move simmove = candidates[i]; -543 apply_move(&simulation, &simmove); -544 if (!is_covered(&simulation, kingrow, kingfile, +543 apply_move(&simulation, &simmove); +544 if (!is_covered(&simulation, kingrow, kingfile, 545 opponent_color(color))) { 546 result = 1; -547 if (threats && threatcount) { +547 if (threats && threatcount) { 548 threats[(*threatcount)++] = candidates[i]; 549 } 550 } @@ -611,23 +611,23 @@ 558 559 static int getlocation(GameState *gamestate, Move *move) { 560 -561 uint8_t color = move->piece & COLOR_MASK; +561 uint8_t color = move->piece & COLOR_MASK; 562 _Bool incheck = gamestate->lastmove?gamestate->lastmove->move.check:0; 563 564 Move threats[16], *threat = NULL; 565 uint8_t threatcount; 566 567 if (get_threats(gamestate, move->torow, move->tofile, color, -568 threats, &threatcount)) { +568 threats, &threatcount)) { 569 570 int reason = INVALID_POSITION; 571 572 // find threats for the specified position 573 for (uint8_t i = 0 ; i < threatcount ; i++) { -574 if ((threats[i].piece & (PIECE_MASK | COLOR_MASK)) -575 == move->piece && +574 if ((threats[i].piece & (PIECE_MASK | COLOR_MASK)) +575 == move->piece && 576 (move->fromrow == POS_UNSPECIFIED || -577 move->fromrow == threats[i].fromrow) && +577 move->fromrow == threats[i].fromrow) && 578 (move->fromfile == POS_UNSPECIFIED || 579 move->fromfile == threats[i].fromfile)) { 580 @@ -635,10 +635,10 @@ 582 return AMBIGUOUS_MOVE; 583 } else { 584 // found threat is no real threat -585 if (is_pinned(gamestate, &(threats[i]))) { +585 if (is_pinned(gamestate, &(threats[i]))) { 586 reason = incheck?KING_IN_CHECK:PIECE_PINNED; 587 } else { -588 threat = &(threats[i]); +588 threat = &(threats[i]); 589 } 590 } 591 } @@ -676,7 +676,7 @@ 623 } 624 625 /* evaluate promotion */ -626 if (len > 3 && mstr[len-2] == '=') { +626 if (len > 3 && mstr[len-2] == '=') { 627 move->promotion = getpiece(mstr[len-1]); 628 if (!move->promotion) { 629 return INVALID_MOVE_SYNTAX; @@ -770,8 +770,8 @@ 717 718 if (move->piece) { 719 if (move->piece == PAWN -720 && move->torow == (color==WHITE?7:0) -721 && !move->promotion) { +720 && move->torow == (color==WHITE?7:0) +721 && !move->promotion) { 722 return NEED_PROMOTION; 723 } 724 @@ -792,7 +792,7 @@ 739 740 Move threats[16]; 741 uint8_t threatcount; -742 if (get_real_threats(gamestate, row, file, color, threats, &threatcount)) { +742 if (get_real_threats(gamestate, row, file, color, threats, &threatcount)) { 743 for (int i = 0 ; i < threatcount ; i++) { 744 if (threats[i].piece != (color|KING)) { 745 return 1; @@ -820,7 +820,7 @@ 767 while (movelist) { 768 time += gameinfo->addtime; 769 -770 struct movetimeval *movetime = &(movelist->move.movetime); +770 struct movetimeval *movetime = &(movelist->move.movetime); 771 if (movetime->tv_sec >= time) { 772 return 0; 773 } @@ -833,10 +833,10 @@ 780 781 time_t sec; 782 movelist = gamestate->lastmove; -783 if ((movelist->move.piece & COLOR_MASK) != color) { -784 struct movetimeval *lastmovetstamp = &(movelist->move.timestamp); +783 if ((movelist->move.piece & COLOR_MASK) != color) { +784 struct movetimeval *lastmovetstamp = &(movelist->move.timestamp); 785 struct timeval currenttstamp; -786 gettimeofday(¤ttstamp, NULL); +786 gettimeofday(&currenttstamp, NULL); 787 micros += currenttstamp.tv_usec - lastmovetstamp->tv_usec; 788 sec = currenttstamp.tv_sec - lastmovetstamp->tv_sec; 789 if (sec >= time) { diff -r 07a3743ce6ac -r 0f1c55d2a90a test/gs/ctest.html --- a/test/gs/ctest.html Thu Jul 11 19:41:06 2024 +0200 +++ b/test/gs/ctest.html Thu Jul 11 20:05:21 2024 +0200 @@ -135,7 +135,7 @@ 82 83 int util_strtoint(char *str, int64_t *value) { 84 char *end; - 85 int64_t val = strtoll(str, &end, 0); + 85 int64_t val = strtoll(str, &end, 0); 86 if(strlen(end) == 0) { 87 *value = val; 88 return 1; @@ -149,9 +149,9 @@ 96 size_t len = strlen(url); 97 int slashcount = 0; 98 int slmax; - 99 if(len > 7 && !strncasecmp(url, "http://", 7)) { + 99 if(len > 7 && !strncasecmp(url, "http://", 7)) { 100 slmax = 3; -101 } else if(len > 8 && !strncasecmp(url, "https://", 8)) { +101 } else if(len > 8 && !strncasecmp(url, "https://", 8)) { 102 slmax = 3; 103 } else { 104 slmax = 1; @@ -265,7 +265,7 @@ 212 213 sstr_t p = sstr(path); 214 ssize_t ntk = 0; -215 sstr_t *tks = sstrsplit(p, S("/"), &ntk); +215 sstr_t *tks = sstrsplit(p, S("/"), &ntk); 216 217 for(int i=0;i<ntk;i++) { 218 sstr_t node = tks[i]; @@ -315,7 +315,7 @@ 262 263 char* util_base64decode(char *in) { 264 int len = 0; -265 return util_base64decode_len(in, &len); +265 return util_base64decode_len(in, &len); 266 } 267 268 char* util_base64decode_len(char* in, int *outlen) { @@ -345,7 +345,7 @@ 292 BIO_write(e, in, len); 293 BIO_flush(e); 294 -295 BIO_get_mem_ptr(e, &mem); +295 BIO_get_mem_ptr(e, &mem); 296 char *out = malloc(mem->length); 297 memcpy(out, mem->data, mem->length -1); 298 out[mem->length - 1] = '\0';