From patchwork Tue Mar 5 20:29:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 46817 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:3944:b0:19e:cdac:8cce with SMTP id ac4csp649196pzc; Tue, 5 Mar 2024 12:30:13 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCX09hogKVYifBJcYJPrgsKyxuxlpgsNOFfjHX/vIJbQGi8TX2IbZD3FFhfY3PvJZKspimivEnIcETB17uAoH0MfrjbkYn2/dP74Hg== X-Google-Smtp-Source: AGHT+IF1zAik7Hsqbxvl4ISeoZDNu/mOABVv+Iasq8SbBWo9yNXg1XKx2ahdq5EgBRGAp791hFY4 X-Received: by 2002:a05:6402:214e:b0:566:59a2:7a10 with SMTP id bq14-20020a056402214e00b0056659a27a10mr3675342edb.1.1709670613519; Tue, 05 Mar 2024 12:30:13 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k11-20020aa7d8cb000000b005677a468cefsi1408358eds.458.2024.03.05.12.30.12; Tue, 05 Mar 2024 12:30:13 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@outlook.com header.s=selector1 header.b=U8veECrD; arc=fail (body hash mismatch); spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=outlook.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4E05968C23A; Tue, 5 Mar 2024 22:30:09 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from EUR02-AM0-obe.outbound.protection.outlook.com (mail-am0eur02olkn2103.outbound.protection.outlook.com [40.92.49.103]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7A72768BA47 for ; Tue, 5 Mar 2024 22:30:03 +0200 (EET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OU52+V7RARrI+WIFDhwlem2yFjKaIucYfDTgdnxmI+po3xN0NVYCloG8iFIzOaJ7OgThaXgBE3utF9SmiRKzpLZpdcQ+Y1aNmoRyzDp02n9rpqjEBkZuDeuGdYEknRtoVJ7wY5NclSv2JIYWKlpivF9Rhqers3wVdzudmsWk00e+w2d1l/n6IByXXfBKsJ3EN7QQ+ct71T9OaTvaBYPNaL2DOkMEbiToAQuKrvUXeFnMsUZkued+RdYgYaWP5g4WvQapbTU2CQqeCx7mbDG8qdZNXKdY3jJsxDFYF8b38aAZanpG0An+pSprr2FBCQoFR9Hk1f6cfch+81Xz29CWyA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=MraQn2L4ANgU0YY0hRUw+60iuonsOs5iLed91Pksjv0=; b=iTpy8uJcaAlix15kqzbnY6wB6JHSZiXr1il16gvNH4EfYCp9ZuWMq8zhXYgv3gQ6iiDrpKA3dB760SSyfSRZi311swenoTuf5LuxmAZomxgOuiLV3ioNpGuiwV8iAEKRDi2G9Srt9YLfHJdUIoz6dI8d714frFFrNz8j6wJDYXsC66fFCR1BQVu4DTcJCkYPwIPmi9UhB5Xq/CiDqxwechcfJK/vFr2F9bimkstW/MvZAlcn0iYooVAntABS6AxXV0/htf9cGeY7l//9KeNMpo2TMzGM++Z6ub2ZgpjbeRcrk334GpOsydXF8Klzrn2ssM7YjE0wvV/mwV+4Hb6tiA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=MraQn2L4ANgU0YY0hRUw+60iuonsOs5iLed91Pksjv0=; b=U8veECrDqOSikfIzMXyKCB0eeK4ARaxOHRgeFSddTQNGQkOpT3VmeOImT8UK/NoSMNXGxKg57/BxsHDGBVu3F4Wp2QJNom64a95bkx1O/jcO5WWxJf5DtqzsCmsyvxWVc6y1axd5gRyviGLkpj5BX0Cc6oLBLJKRCZfATM9b1eTp2I3JoyhBFKir+tKgI+f6pIFZIpS+fo478BQqnKlu1L1txrjZqJjzeNmCBET0tIe+r/fIvlfbp08HsalsApgYlMfYwS1xGt0YQlL+dEjr2aC+VE8YaCFVt5U2/Oal4OLztx+jtUZ74Cjm5BHzX6xTriYqVTu35Ky6kLFtnfbaLg== Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) by DU0P250MB0434.EURP250.PROD.OUTLOOK.COM (2603:10a6:10:346::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7339.39; Tue, 5 Mar 2024 20:30:01 +0000 Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::65aa:deb0:a18e:d48d]) by AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::65aa:deb0:a18e:d48d%5]) with mapi id 15.20.7316.023; Tue, 5 Mar 2024 20:30:01 +0000 From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Tue, 5 Mar 2024 21:29:53 +0100 Message-ID: X-Mailer: git-send-email 2.40.1 X-TMN: [MBzkSkGgDg0JnuN0Js9v9MNd3/o/cnK7KK43/6FoR40=] X-ClientProxiedBy: ZRAP278CA0016.CHEP278.PROD.OUTLOOK.COM (2603:10a6:910:10::26) To AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) X-Microsoft-Original-Message-ID: <20240305202953.2929446-1-andreas.rheinhardt@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AS8P250MB0744:EE_|DU0P250MB0434:EE_ X-MS-Office365-Filtering-Correlation-Id: 9c51bad6-5098-4ec7-f06f-08dc3d530842 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 3m78lz5MaUGomXeQ6i0g7QyQqR1cNvKonqq/wFOGoOc3fnk8svh5EyGE2JoGxKj3vZT58o4Xm4xunOU8QG9jLxPpPtzIPjqskWxFXuuUfkQv8k0m4OAA2utfZf+gp2VYxUsFlnj2+SuimNY/MuVCG40U+rq58vr1mQNfxhAzTYxiBdkWfQlA1D/m+pt6TvGTyOU+OuMXzOC6NWrGPKlFrjJ1rBA6sDTFBQKrnUNU55Oc4GBCqAgKBQ5Z3o5HPfs+esbeYDYH2uenjSTk5Q/2p7Ie1YV1KfM7uP/cdFQ914RhkN1xV/4ElCgQz1EllN6c5grYSK+gYVY05Q8es2BD0c+1BaVkts2edhju738nPIXQ8bqzjb3t/Q78o0iGTn36+KSPfdpRJ3t9vax00sS/xJuq7vT0SEeEhWVCIL7pOHkPRWMXubPv414Q/8cBn4U779C6CkpEVcD7mB4uK5jQ7YtTirsxBlQUeSVj81JT2aSba7xB0JTtY3hp3u1yt9Q+1xgBqbtBzutk+wafvwUoMhFJzI7F0HnwkiTHiB7b/INjI3Q4QdZ8vdUfKfa7bStwYRFfleukWOIubPzvzNmmdJDz8C9oDS8XTJP1ixyv7n/UjtsEqgB9JdiWugSp8c3G4UEm7wuE4+iy9BwgqmMatEinKbrYtB3Lg9F0QgrvAX4LMv/J9LDCaXeL11dHQE6O X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: datF3mLZi14MyOW5NuyK3BQAL34ssY9y7hLhTUGXmZZIB3bgJSbGwfgtLirEo7ONK7rjOVny5KvQZjOABX18NVP3Vuf7sAX71ib1WoY+Ea1+Gn9p2iVwqDDAH9WeQvBzAGx0AJJjlAuEZLqmJyVHTJcJCx5OO78FvGNBnX5l1uPwS32TZnNhBmguY23RiXkSS2yREDr95GjtnzZuO6nF348V8y/ZvS5Fuci3q+Iz5pmbMnRNh8zCBJqsbY11C/LInheOO6e8mQqtLlZJdIMp19RpFFIYjKLvfKpnQ4T+aYtHfG2vx3RQuhSY46ZE+FASNHwW4TMszVAC6StKq25Osy9FhP8oehAYDRzWZWoFHOGCCN3YdgP6XQB+pwQTgvznur3l3jnNNThq42Hc0CUNaoqxRg3l9k+ZLru30IiXHAvK21H6SysQqtGuwjOw9WeBcA1pxJqrJMkKiQoNPMz/gCxv6pZ+Osg6ksraC7rbtMBKReTMasmeoENsQuHDhcZf0WbGFq73Dwta1oK96uAdS3qGyblvOlz6CLVuOdmEnrNd3cIMMQA6OZCu7PNj1uA8vFW5Msr9QyD1O5hl+YkobvyhTxKoVNdJ8Ps6HpaxLPMZZU9fClhwVx+eiYVZa0P7AmDlCDTdX/ZkIrPuhtDve+p4GAFwFmDh6ATw2sbZJ1i2oO+lTeAmNCQUlJpx0PGNPnPkKbiEJX/RDXahAUbLdQK5ycWiOf6V1coTNcWC5t5qDKS1uEC23GzB/do0hlb7fXNn91WGRoQZdhHO7lR8DvJlNl28MWP0WEyXg1jWQEhkqY0eDCkRTGBRKWH18jGUww6bM3Xy7noQkNwpmoHfCH3IAh/HULMuzMpRmNuHuFo7x3/ZVPhccEJvWV8WP6u63l0uY65TctzUsF0gmMciZR5ndosBa5DGqlyUC5V8OAjzJ0XuYGgGZhKwhkkEULbMH/Fqr3OTE+kUAMmRS9l6DG2XGbWosRYq8sjKI1bc7MOWegimynMIMuQeOki+HB7ZevlKAacsfEcOrzI2QTZOs3/q5JB6HE4Ni0lyzYXgFur4vMwuUtwCykZz1YTQ+WtCTQNjiCGMjsHBTK9uA6DCBp1hCA/6d59pK8NlDwWOmHrMDzqqtInc3EZCbYhdd6dKtbhIcxdb/p4vICEpXx2UO53ta04835ch7bv5LDMZobgGIFayePZteDBwJyWFrrOyW/kDSCl+n06/2u4YvrbvQrvO1QU6dByCKXSlRPl5gRdQ95t8R/ylekEvI+PsVK2IA7ZutvAwhtAgiZDbwVXmcg== X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 9c51bad6-5098-4ec7-f06f-08dc3d530842 X-MS-Exchange-CrossTenant-AuthSource: AS8P250MB0744.EURP250.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Mar 2024 20:30:01.1931 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DU0P250MB0434 Subject: [FFmpeg-devel] [PATCH] avcodec/ccaption_dec: Avoid relocations for strings X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: ZQPM/Ld3cAJ7 The longest string here takes four bytes, so using an array of pointers is wasteful even when ignoring the cost of relocations; the lack of relocations also implies that this array will now be put into .rodata and not into .data.rel.ro. Static asserts are used to ensure that all strings are always properly zero-terminated. Signed-off-by: Andreas Rheinhardt --- Now using static asserts to address the main point of criticism in https://patchwork.ffmpeg.org/project/ffmpeg/patch/20210106081702.2495510-1-andreas.rheinhardt@gmail.com/ libavcodec/ccaption_dec.c | 215 ++++++++++++++++++++------------------ 1 file changed, 115 insertions(+), 100 deletions(-) diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c index 95143e7e46..1550e4b253 100644 --- a/libavcodec/ccaption_dec.c +++ b/libavcodec/ccaption_dec.c @@ -67,108 +67,123 @@ enum cc_charset { CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH, }; -static const char *charset_overrides[4][128] = +#define CHARSET_OVERRIDE_LIST(START_SET, ENTRY, END_SET) \ + START_SET(CCSET_BASIC_AMERICAN) \ + ENTRY(0x27, "\u2019") \ + ENTRY(0x2a, "\u00e1") \ + ENTRY(0x5c, "\u00e9") \ + ENTRY(0x5e, "\u00ed") \ + ENTRY(0x5f, "\u00f3") \ + ENTRY(0x60, "\u00fa") \ + ENTRY(0x7b, "\u00e7") \ + ENTRY(0x7c, "\u00f7") \ + ENTRY(0x7d, "\u00d1") \ + ENTRY(0x7e, "\u00f1") \ + ENTRY(0x7f, "\u2588") \ + END_SET \ + START_SET(CCSET_SPECIAL_AMERICAN) \ + ENTRY(0x30, "\u00ae") \ + ENTRY(0x31, "\u00b0") \ + ENTRY(0x32, "\u00bd") \ + ENTRY(0x33, "\u00bf") \ + ENTRY(0x34, "\u2122") \ + ENTRY(0x35, "\u00a2") \ + ENTRY(0x36, "\u00a3") \ + ENTRY(0x37, "\u266a") \ + ENTRY(0x38, "\u00e0") \ + ENTRY(0x39, "\u00A0") \ + ENTRY(0x3a, "\u00e8") \ + ENTRY(0x3b, "\u00e2") \ + ENTRY(0x3c, "\u00ea") \ + ENTRY(0x3d, "\u00ee") \ + ENTRY(0x3e, "\u00f4") \ + ENTRY(0x3f, "\u00fb") \ + END_SET \ + START_SET(CCSET_EXTENDED_SPANISH_FRENCH_MISC) \ + ENTRY(0x20, "\u00c1") \ + ENTRY(0x21, "\u00c9") \ + ENTRY(0x22, "\u00d3") \ + ENTRY(0x23, "\u00da") \ + ENTRY(0x24, "\u00dc") \ + ENTRY(0x25, "\u00fc") \ + ENTRY(0x26, "\u00b4") \ + ENTRY(0x27, "\u00a1") \ + ENTRY(0x28, "*") \ + ENTRY(0x29, "\u2018") \ + ENTRY(0x2a, "-") \ + ENTRY(0x2b, "\u00a9") \ + ENTRY(0x2c, "\u2120") \ + ENTRY(0x2d, "\u00b7") \ + ENTRY(0x2e, "\u201c") \ + ENTRY(0x2f, "\u201d") \ + ENTRY(0x30, "\u00c0") \ + ENTRY(0x31, "\u00c2") \ + ENTRY(0x32, "\u00c7") \ + ENTRY(0x33, "\u00c8") \ + ENTRY(0x34, "\u00ca") \ + ENTRY(0x35, "\u00cb") \ + ENTRY(0x36, "\u00eb") \ + ENTRY(0x37, "\u00ce") \ + ENTRY(0x38, "\u00cf") \ + ENTRY(0x39, "\u00ef") \ + ENTRY(0x3a, "\u00d4") \ + ENTRY(0x3b, "\u00d9") \ + ENTRY(0x3c, "\u00f9") \ + ENTRY(0x3d, "\u00db") \ + ENTRY(0x3e, "\u00ab") \ + ENTRY(0x3f, "\u00bb") \ + END_SET \ + START_SET(CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH) \ + ENTRY(0x20, "\u00c3") \ + ENTRY(0x21, "\u00e3") \ + ENTRY(0x22, "\u00cd") \ + ENTRY(0x23, "\u00cc") \ + ENTRY(0x24, "\u00ec") \ + ENTRY(0x25, "\u00d2") \ + ENTRY(0x26, "\u00f2") \ + ENTRY(0x27, "\u00d5") \ + ENTRY(0x28, "\u00f5") \ + ENTRY(0x29, "{") \ + ENTRY(0x2a, "}") \ + ENTRY(0x2b, "\\") \ + ENTRY(0x2c, "^") \ + ENTRY(0x2d, "_") \ + ENTRY(0x2e, "|") \ + ENTRY(0x2f, "~") \ + ENTRY(0x30, "\u00c4") \ + ENTRY(0x31, "\u00e4") \ + ENTRY(0x32, "\u00d6") \ + ENTRY(0x33, "\u00f6") \ + ENTRY(0x34, "\u00df") \ + ENTRY(0x35, "\u00a5") \ + ENTRY(0x36, "\u00a4") \ + ENTRY(0x37, "\u00a6") \ + ENTRY(0x38, "\u00c5") \ + ENTRY(0x39, "\u00e5") \ + ENTRY(0x3a, "\u00d8") \ + ENTRY(0x3b, "\u00f8") \ + ENTRY(0x3c, "\u250c") \ + ENTRY(0x3d, "\u2510") \ + ENTRY(0x3e, "\u2514") \ + ENTRY(0x3f, "\u2518") \ + END_SET \ + +static const char charset_overrides[4][128][sizeof("\u266a")] = { - [CCSET_BASIC_AMERICAN] = { - [0x27] = "\u2019", - [0x2a] = "\u00e1", - [0x5c] = "\u00e9", - [0x5e] = "\u00ed", - [0x5f] = "\u00f3", - [0x60] = "\u00fa", - [0x7b] = "\u00e7", - [0x7c] = "\u00f7", - [0x7d] = "\u00d1", - [0x7e] = "\u00f1", - [0x7f] = "\u2588" - }, - [CCSET_SPECIAL_AMERICAN] = { - [0x30] = "\u00ae", - [0x31] = "\u00b0", - [0x32] = "\u00bd", - [0x33] = "\u00bf", - [0x34] = "\u2122", - [0x35] = "\u00a2", - [0x36] = "\u00a3", - [0x37] = "\u266a", - [0x38] = "\u00e0", - [0x39] = "\u00A0", - [0x3a] = "\u00e8", - [0x3b] = "\u00e2", - [0x3c] = "\u00ea", - [0x3d] = "\u00ee", - [0x3e] = "\u00f4", - [0x3f] = "\u00fb", - }, - [CCSET_EXTENDED_SPANISH_FRENCH_MISC] = { - [0x20] = "\u00c1", - [0x21] = "\u00c9", - [0x22] = "\u00d3", - [0x23] = "\u00da", - [0x24] = "\u00dc", - [0x25] = "\u00fc", - [0x26] = "\u00b4", - [0x27] = "\u00a1", - [0x28] = "*", - [0x29] = "\u2018", - [0x2a] = "-", - [0x2b] = "\u00a9", - [0x2c] = "\u2120", - [0x2d] = "\u00b7", - [0x2e] = "\u201c", - [0x2f] = "\u201d", - [0x30] = "\u00c0", - [0x31] = "\u00c2", - [0x32] = "\u00c7", - [0x33] = "\u00c8", - [0x34] = "\u00ca", - [0x35] = "\u00cb", - [0x36] = "\u00eb", - [0x37] = "\u00ce", - [0x38] = "\u00cf", - [0x39] = "\u00ef", - [0x3a] = "\u00d4", - [0x3b] = "\u00d9", - [0x3c] = "\u00f9", - [0x3d] = "\u00db", - [0x3e] = "\u00ab", - [0x3f] = "\u00bb", - }, - [CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH] = { - [0x20] = "\u00c3", - [0x21] = "\u00e3", - [0x22] = "\u00cd", - [0x23] = "\u00cc", - [0x24] = "\u00ec", - [0x25] = "\u00d2", - [0x26] = "\u00f2", - [0x27] = "\u00d5", - [0x28] = "\u00f5", - [0x29] = "{", - [0x2a] = "}", - [0x2b] = "\\", - [0x2c] = "^", - [0x2d] = "_", - [0x2e] = "|", - [0x2f] = "~", - [0x30] = "\u00c4", - [0x31] = "\u00e4", - [0x32] = "\u00d6", - [0x33] = "\u00f6", - [0x34] = "\u00df", - [0x35] = "\u00a5", - [0x36] = "\u00a4", - [0x37] = "\u00a6", - [0x38] = "\u00c5", - [0x39] = "\u00e5", - [0x3a] = "\u00d8", - [0x3b] = "\u00f8", - [0x3c] = "\u250c", - [0x3d] = "\u2510", - [0x3e] = "\u2514", - [0x3f] = "\u2518", +#define START_SET(IDX) \ + [IDX] = { +#define ENTRY(idx, string) \ + [idx] = string, +#define END_SET \ }, + CHARSET_OVERRIDE_LIST(START_SET, ENTRY, END_SET) }; +#define EMPTY_START(IDX) +#define EMPTY_END +#define ASSERT_ENTRY(IDX, str) \ + _Static_assert(sizeof(str) <= sizeof(charset_overrides[0][0]), \ + "'" str "' string takes too much space"); +CHARSET_OVERRIDE_LIST(EMPTY_START, ASSERT_ENTRY, EMPTY_END) static const unsigned char bg_attribs[8] = // Color { @@ -571,7 +586,7 @@ static int capture_screen(CCaptionSubContext *ctx) prev_color = color[j]; prev_bg_color = bg[j]; override = charset_overrides[(int)charset[j]][(int)row[j]]; - if (override) { + if (override[0]) { av_bprintf(&ctx->buffer[bidx], "%s%s%s%s%s", e_tag, s_tag, c_tag, b_tag, override); seen_char = 1; } else if (row[j] == ' ' && !seen_char) {