strgen/strgen.c
changeset 5108 aeaef6fe53b7
parent 4922 dec2c076d5a7
child 5111 ee7472776a4d
equal deleted inserted replaced
5107:f3cddd9ce5f4 5108:aeaef6fe53b7
     1 /* $Id$ */
     1 /* $Id$ */
     2 
     2 
     3 #include "../stdafx.h"
     3 #include "../stdafx.h"
     4 #include "../macros.h"
     4 #include "../macros.h"
     5 #include "../string.h"
     5 #include "../string.h"
       
     6 #include "../table/control_codes.h"
     6 #include <stdio.h>
     7 #include <stdio.h>
     7 #include <string.h>
     8 #include <string.h>
     8 #include <stdlib.h>
     9 #include <stdlib.h>
     9 #include <stdarg.h>
    10 #include <stdarg.h>
    10 
    11 
   197 	if (_put_pos == lengthof(_put_buf)) fatal("Put buffer too small");
   198 	if (_put_pos == lengthof(_put_buf)) fatal("Put buffer too small");
   198 	_put_buf[_put_pos++] = c;
   199 	_put_buf[_put_pos++] = c;
   199 }
   200 }
   200 
   201 
   201 
   202 
   202 static void EmitSingleByte(char *buf, int value)
   203 static void PutUtf8(uint32 value)
       
   204 {
       
   205 	if (value < 0x80) {
       
   206 		PutByte(value);
       
   207 	} else if (value < 0x800) {
       
   208 		PutByte(0xC0 + GB(value,  6, 5));
       
   209 		PutByte(0x80 + GB(value,  0, 6));
       
   210 	} else if (value < 0x10000) {
       
   211 		PutByte(0xE0 + GB(value, 12, 4));
       
   212 		PutByte(0x80 + GB(value,  6, 6));
       
   213 		PutByte(0x80 + GB(value,  0, 6));
       
   214 	} else if (value < 0x110000) {
       
   215 		PutByte(0xF0 + GB(value, 18, 3));
       
   216 		PutByte(0x80 + GB(value, 12, 6));
       
   217 		PutByte(0x80 + GB(value,  6, 6));
       
   218 		PutByte(0x80 + GB(value,  0, 6));
       
   219 	} else {
       
   220 		warning("Invalid unicode value U+0x%X\n", value);
       
   221 	}
       
   222 }
       
   223 
       
   224 
       
   225 static void EmitSingleChar(char *buf, int value)
   203 {
   226 {
   204 	if (*buf != '\0') warning("Ignoring trailing letters in command");
   227 	if (*buf != '\0') warning("Ignoring trailing letters in command");
   205 	PutByte((byte)value);
   228 	PutUtf8(value);
   206 }
   229 }
   207 
   230 
   208 
       
   209 static void EmitEscapedByte(char *buf, int value)
       
   210 {
       
   211 	if (*buf != '\0') warning("Ignoring trailing letters in command");
       
   212 	PutByte(0x85);
       
   213 	PutByte((byte)value);
       
   214 }
       
   215 
   231 
   216 static void EmitSetX(char *buf, int value)
   232 static void EmitSetX(char *buf, int value)
   217 {
   233 {
   218 	char *err;
   234 	char *err;
   219 	int x = strtol(buf, &err, 0);
   235 	int x = strtol(buf, &err, 0);
   220 	if (*err != 0) fatal("SetX param invalid");
   236 	if (*err != 0) fatal("SetX param invalid");
   221 	PutByte(1);
   237 	PutUtf8(SCC_SETX);
   222 	PutByte((byte)x);
   238 	PutByte((byte)x);
   223 }
   239 }
   224 
   240 
   225 
   241 
   226 static void EmitSetXY(char *buf, int value)
   242 static void EmitSetXY(char *buf, int value)
   232 	x = strtol(buf, &err, 0);
   248 	x = strtol(buf, &err, 0);
   233 	if (*err != ' ') fatal("SetXY param invalid");
   249 	if (*err != ' ') fatal("SetXY param invalid");
   234 	y = strtol(err + 1, &err, 0);
   250 	y = strtol(err + 1, &err, 0);
   235 	if (*err != 0) fatal("SetXY param invalid");
   251 	if (*err != 0) fatal("SetXY param invalid");
   236 
   252 
   237 	PutByte(2);
   253 	PutUtf8(SCC_SETXY);
   238 	PutByte((byte)x);
   254 	PutByte((byte)x);
   239 	PutByte((byte)y);
   255 	PutByte((byte)y);
   240 }
   256 }
   241 
   257 
   242 // The plural specifier looks like
   258 // The plural specifier looks like
   350 				}
   366 				}
   351 			}
   367 			}
   352 		}
   368 		}
   353 	}
   369 	}
   354 
   370 
   355 	PutByte(0x8D);
   371 	PutUtf8(SCC_PLURAL_LIST);
   356 	PutByte(TranslateArgumentIdx(argidx));
   372 	PutByte(TranslateArgumentIdx(argidx));
   357 	EmitWordList(words, nw);
   373 	EmitWordList(words, nw);
   358 }
   374 }
   359 
   375 
   360 
   376 
   370 		for (nw = 0; ; nw++) {
   386 		for (nw = 0; ; nw++) {
   371 			if (nw >= 8) fatal("G argument '%s' invalid", buf);
   387 			if (nw >= 8) fatal("G argument '%s' invalid", buf);
   372 			if (strcmp(buf, _genders[nw]) == 0) break;
   388 			if (strcmp(buf, _genders[nw]) == 0) break;
   373 		}
   389 		}
   374 		// now nw contains the gender index
   390 		// now nw contains the gender index
   375 		PutByte(0x87);
   391 		PutUtf8(SCC_GENDER_INDEX);
   376 		PutByte(nw);
   392 		PutByte(nw);
   377 	} else {
   393 	} else {
   378 		const char* words[8];
   394 		const char* words[8];
   379 
   395 
   380 		// This is a {G 0 foo bar two} command.
   396 		// This is a {G 0 foo bar two} command.
   384 		for (nw = 0; nw < 8; nw++) {
   400 		for (nw = 0; nw < 8; nw++) {
   385 			words[nw] = ParseWord(&buf);
   401 			words[nw] = ParseWord(&buf);
   386 			if (words[nw] == NULL) break;
   402 			if (words[nw] == NULL) break;
   387 		}
   403 		}
   388 		if (nw != _numgenders) fatal("Bad # of arguments for gender command");
   404 		if (nw != _numgenders) fatal("Bad # of arguments for gender command");
   389 		PutByte(0x85);
   405 		PutUtf8(SCC_GENDER_LIST);
   390 		PutByte(13);
       
   391 		PutByte(TranslateArgumentIdx(argidx));
   406 		PutByte(TranslateArgumentIdx(argidx));
   392 		EmitWordList(words, nw);
   407 		EmitWordList(words, nw);
   393 	}
   408 	}
   394 }
   409 }
   395 
   410 
   396 
   411 
   397 static const CmdStruct _cmd_structs[] = {
   412 static const CmdStruct _cmd_structs[] = {
   398 	// Update position
   413 	// Update position
   399 	{"SETX",  EmitSetX,  1, 0, 0},
   414 	{"SETX",  EmitSetX,  SCC_SETX,  0, 0},
   400 	{"SETXY", EmitSetXY, 2, 0, 0},
   415 	{"SETXY", EmitSetXY, SCC_SETXY, 0, 0},
   401 
   416 
   402 	// Font size
   417 	// Font size
   403 	{"TINYFONT", EmitSingleByte, 8, 0, 0},
   418 	{"TINYFONT", EmitSingleChar, SCC_TINYFONT, 0, 0},
   404 	{"BIGFONT",  EmitSingleByte, 9, 0, 0},
   419 	{"BIGFONT",  EmitSingleChar, SCC_BIGFONT,  0, 0},
   405 
   420 
   406 	// Colors
   421 	// Colors
   407 	{"BLUE",    EmitSingleByte, 15, 0, 0},
   422 	{"BLUE",    EmitSingleChar, SCC_BLUE,    0, 0},
   408 	{"SILVER",  EmitSingleByte, 16, 0, 0},
   423 	{"SILVER",  EmitSingleChar, SCC_SILVER,  0, 0},
   409 	{"GOLD",    EmitSingleByte, 17, 0, 0},
   424 	{"GOLD",    EmitSingleChar, SCC_GOLD,    0, 0},
   410 	{"RED",     EmitSingleByte, 18, 0, 0},
   425 	{"RED",     EmitSingleChar, SCC_RED,     0, 0},
   411 	{"PURPLE",  EmitSingleByte, 19, 0, 0},
   426 	{"PURPLE",  EmitSingleChar, SCC_PURPLE,  0, 0},
   412 	{"LTBROWN", EmitSingleByte, 20, 0, 0},
   427 	{"LTBROWN", EmitSingleChar, SCC_LTBROWN, 0, 0},
   413 	{"ORANGE",  EmitSingleByte, 21, 0, 0},
   428 	{"ORANGE",  EmitSingleChar, SCC_ORANGE,  0, 0},
   414 	{"GREEN",   EmitSingleByte, 22, 0, 0},
   429 	{"GREEN",   EmitSingleChar, SCC_GREEN,   0, 0},
   415 	{"YELLOW",  EmitSingleByte, 23, 0, 0},
   430 	{"YELLOW",  EmitSingleChar, SCC_YELLOW,  0, 0},
   416 	{"DKGREEN", EmitSingleByte, 24, 0, 0},
   431 	{"DKGREEN", EmitSingleChar, SCC_DKGREEN, 0, 0},
   417 	{"CREAM",   EmitSingleByte, 25, 0, 0},
   432 	{"CREAM",   EmitSingleChar, SCC_CREAM,   0, 0},
   418 	{"BROWN",   EmitSingleByte, 26, 0, 0},
   433 	{"BROWN",   EmitSingleChar, SCC_BROWN,   0, 0},
   419 	{"WHITE",   EmitSingleByte, 27, 0, 0},
   434 	{"WHITE",   EmitSingleChar, SCC_WHITE,   0, 0},
   420 	{"LTBLUE",  EmitSingleByte, 28, 0, 0},
   435 	{"LTBLUE",  EmitSingleChar, SCC_LTBLUE,  0, 0},
   421 	{"GRAY",    EmitSingleByte, 29, 0, 0},
   436 	{"GRAY",    EmitSingleChar, SCC_GRAY,    0, 0},
   422 	{"DKBLUE",  EmitSingleByte, 30, 0, 0},
   437 	{"DKBLUE",  EmitSingleChar, SCC_DKBLUE,  0, 0},
   423 	{"BLACK",   EmitSingleByte, 31, 0, 0},
   438 	{"BLACK",   EmitSingleChar, SCC_BLACK,   0, 0},
   424 
   439 
   425 	{"CURRCOMPACT",   EmitEscapedByte, 0, 1, 0}, // compact currency (32 bits)
   440 	{"CURRCOMPACT",   EmitSingleChar, SCC_CURRENCY_COMPACT,    1, 0}, // compact currency (32 bits)
   426 	{"REV",           EmitEscapedByte, 2, 0, 0}, // openttd revision string
   441 	{"REV",           EmitSingleChar, SCC_REVISION,            0, 0}, // openttd revision string
   427 	{"SHORTCARGO",    EmitEscapedByte, 3, 2, 0}, // short cargo description, only ### tons, or ### litres
   442 	{"SHORTCARGO",    EmitSingleChar, SCC_CARGO_SHORT,         2, 0}, // short cargo description, only ### tons, or ### litres
   428 	{"CURRCOMPACT64", EmitEscapedByte, 4, 2, 0}, // compact currency 64 bits
   443 	{"CURRCOMPACT64", EmitSingleChar, SCC_CURRENCY_COMPACT_64, 2, 0}, // compact currency 64 bits
   429 
   444 
   430 	// These are special versions of {STRING1}
   445 	// These are special versions of {STRING1}
   431 	// The first string includes the second string.
   446 	// The first string includes the second string.
   432 	{"COMPANY",    EmitEscapedByte, 5, 1, 0},
   447 	{"COMPANY",    EmitSingleChar, SCC_STRING1, 1, 0},
   433 	{"PLAYERNAME", EmitEscapedByte, 5, 1, 0},
   448 	{"PLAYERNAME", EmitSingleChar, SCC_STRING1, 1, 0},
   434 	{"VEHICLE",    EmitEscapedByte, 5, 1, 0},
   449 	{"VEHICLE",    EmitSingleChar, SCC_STRING1, 1, 0},
   435 
   450 
   436 	{"STRING1", EmitEscapedByte, 5, 1, C_CASE}, // included string that consumes ONE argument
   451 	{"STRING1", EmitSingleChar, SCC_STRING1, 1, C_CASE}, // included string that consumes ONE argument
   437 	{"STRING2", EmitEscapedByte, 6, 2, C_CASE}, // included string that consumes TWO arguments
   452 	{"STRING2", EmitSingleChar, SCC_STRING2, 2, C_CASE}, // included string that consumes TWO arguments
   438 	{"STRING3", EmitEscapedByte, 7, 3, C_CASE}, // included string that consumes THREE arguments
   453 	{"STRING3", EmitSingleChar, SCC_STRING3, 3, C_CASE}, // included string that consumes THREE arguments
   439 	{"STRING4", EmitEscapedByte, 8, 4, C_CASE}, // included string that consumes FOUR arguments
   454 	{"STRING4", EmitSingleChar, SCC_STRING4, 4, C_CASE}, // included string that consumes FOUR arguments
   440 	{"STRING5", EmitEscapedByte, 9, 5, C_CASE}, // included string that consumes FIVE arguments
   455 	{"STRING5", EmitSingleChar, SCC_STRING5, 5, C_CASE}, // included string that consumes FIVE arguments
   441 
   456 
   442 	{"STATIONFEATURES", EmitEscapedByte, 10, 1, 0}, // station features string, icons of the features
   457 	{"STATIONFEATURES", EmitSingleChar, SCC_STATION_FEATURES, 1, 0}, // station features string, icons of the features
   443 	{"INDUSTRY",        EmitEscapedByte, 11, 1, 0}, // industry, takes an industry #
   458 	{"INDUSTRY",        EmitSingleChar, SCC_INDUSTRY_NAME,    1, 0}, // industry, takes an industry #
   444 	{"VOLUME",          EmitEscapedByte, 12, 1, 0},
   459 	{"CARGO",           EmitSingleChar, SCC_CARGO,            2, 0},
   445 	{"DATE_TINY",       EmitEscapedByte, 14, 1, 0},
   460 	{"POWER",           EmitSingleChar, SCC_POWER,            1, 0},
   446 	{"CARGO",           EmitEscapedByte, 15, 2, 0},
   461 	{"VOLUME",          EmitSingleChar, SCC_VOLUME,           1, 0},
   447 	{"POWER",           EmitEscapedByte, 16, 1, 0},
   462 	{"VOLUME_S",        EmitSingleChar, SCC_VOLUME_SHORT,     1, 0},
   448 	{"VOLUME_S",        EmitEscapedByte, 17, 1, 0},
   463 	{"WEIGHT",          EmitSingleChar, SCC_WEIGHT,           1, 0},
   449 	{"WEIGHT",          EmitEscapedByte, 18, 1, 0},
   464 	{"WEIGHT_S",        EmitSingleChar, SCC_WEIGHT_SHORT,     1, 0},
   450 	{"WEIGHT_S",        EmitEscapedByte, 19, 1, 0},
   465 	{"FORCE",           EmitSingleChar, SCC_FORCE,            1, 0},
   451 	{"FORCE",           EmitEscapedByte, 20, 1, 0},
   466 	{"VELOCITY",        EmitSingleChar, SCC_VELOCITY,         1, 0},
   452 
   467 
   453 	{"P", EmitPlural, 0, 0, C_DONTCOUNT}, // plural specifier
   468 	{"P", EmitPlural, 0, 0, C_DONTCOUNT}, // plural specifier
   454 	{"G", EmitGender, 0, 0, C_DONTCOUNT}, // gender specifier
   469 	{"G", EmitGender, 0, 0, C_DONTCOUNT}, // gender specifier
   455 
   470 
   456 	{"DATE_LONG",  EmitSingleByte, 0x82, 1, 0},
   471 	{"DATE_TINY",  EmitSingleChar, SCC_DATE_TINY, 1, 0},
   457 	{"DATE_SHORT", EmitSingleByte, 0x83, 1, 0},
   472 	{"DATE_SHORT", EmitSingleChar, SCC_DATE_SHORT, 1, 0},
   458 
   473 	{"DATE_LONG",  EmitSingleChar, SCC_DATE_LONG, 1, 0},
   459 	{"VELOCITY", EmitSingleByte, 0x84, 1, 0},
   474 
   460 
   475 	{"SKIP", EmitSingleChar, SCC_SKIP, 1, 0},
   461 	// 0x85 is the marker for escaped commands
   476 
   462 
   477 	{"STRING", EmitSingleChar, SCC_STRING, 1, C_CASE},
   463 	{"SKIP", EmitSingleByte, 0x86, 1, 0},
       
   464 
       
   465 	{"STRING", EmitSingleByte, 0x88, 1, C_CASE},
       
   466 
   478 
   467 	// Numbers
   479 	// Numbers
   468 	{"COMMA", EmitSingleByte, 0x8B, 1, 0}, // Number with comma
   480 	{"COMMA", EmitSingleChar, SCC_COMMA, 1, 0}, // Number with comma
   469 	{"NUM",   EmitSingleByte, 0x8E, 1, 0}, // Signed number
   481 	{"NUM",   EmitSingleChar, SCC_NUM,   1, 0}, // Signed number
   470 
   482 
   471 	{"CURRENCY",   EmitSingleByte, 0x8F, 1, 0},
   483 	{"CURRENCY",   EmitSingleChar, SCC_CURRENCY,    1, 0},
   472 	{"CURRENCY64", EmitSingleByte, 0x9C, 2, 0},
   484 	{"CURRENCY64", EmitSingleChar, SCC_CURRENCY_64, 2, 0},
   473 
   485 
   474 	{"WAYPOINT", EmitSingleByte, 0x99, 1, 0}, // waypoint name
   486 	{"WAYPOINT", EmitSingleChar, SCC_WAYPOINT_NAME, 1, 0}, // waypoint name
   475 	{"STATION",  EmitSingleByte, 0x9A, 1, 0},
   487 	{"STATION",  EmitSingleChar, SCC_STATION_NAME,  1, 0},
   476 	{"TOWN",     EmitSingleByte, 0x9B, 1, 0},
   488 	{"TOWN",     EmitSingleChar, SCC_TOWN_NAME,     1, 0},
   477 
   489 
   478 	// 0x9D is used for the pseudo command SETCASE
   490 	// 0x9D is used for the pseudo command SETCASE
   479 	// 0x9E is used for case switching
   491 	// 0x9E is used for case switching
   480 
   492 
   481 	{"",               EmitSingleByte, '\n', 0, C_DONTCOUNT},
   493 	{"",               EmitSingleChar, '\n',               0, C_DONTCOUNT},
   482 	{"{",              EmitSingleByte, '{',  0, C_DONTCOUNT},
   494 	{"{",              EmitSingleChar, '{',                0, C_DONTCOUNT},
   483 	{"UPARROW",        EmitSingleByte, 0x80, 0, 0},
   495 	{"UPARROW",        EmitSingleChar, SCC_UPARROW,        0, 0},
   484 	{"SMALLUPARROW",   EmitSingleByte, 0x90, 0, 0},
   496 	{"SMALLUPARROW",   EmitSingleChar, SCC_SMALLUPARROW,   0, 0},
   485 	{"SMALLDOWNARROW", EmitSingleByte, 0x91, 0, 0},
   497 	{"SMALLDOWNARROW", EmitSingleChar, SCC_SMALLDOWNARROW, 0, 0},
   486 	{"TRAIN",          EmitSingleByte, 0x94, 0, 0},
   498 	{"TRAIN",          EmitSingleChar, SCC_TRAIN,          0, 0},
   487 	{"LORRY",          EmitSingleByte, 0x95, 0, 0},
   499 	{"LORRY",          EmitSingleChar, SCC_LORRY,          0, 0},
   488 	{"BUS",            EmitSingleByte, 0x96, 0, 0},
   500 	{"BUS",            EmitSingleChar, SCC_BUS,            0, 0},
   489 	{"PLANE",          EmitSingleByte, 0x97, 0, 0},
   501 	{"PLANE",          EmitSingleChar, SCC_PLANE,          0, 0},
   490 	{"SHIP",           EmitSingleByte, 0x98, 0, 0},
   502 	{"SHIP",           EmitSingleChar, SCC_SHIP,           0, 0},
   491 	{"NBSP",           EmitSingleByte, 0xA0, 0, C_DONTCOUNT},
   503 	{"NBSP",           EmitSingleChar, 0xA0,               0, C_DONTCOUNT},
   492 	{"CENT",           EmitSingleByte, '¢',  0, C_DONTCOUNT},
   504 	{"CENT",           EmitSingleChar, 0xA2,               0, C_DONTCOUNT},
   493 	{"POUNDSIGN",      EmitSingleByte, '£',  0, C_DONTCOUNT},
   505 	{"POUNDSIGN",      EmitSingleChar, 0xA3,               0, C_DONTCOUNT},
   494 	{"EURO",           EmitSingleByte, '¤',  0, C_DONTCOUNT},
   506 	{"EURO",           EmitSingleChar, 0x20AC,             0, C_DONTCOUNT},
   495 	{"YENSIGN",        EmitSingleByte, '¥',  0, C_DONTCOUNT},
   507 	{"YENSIGN",        EmitSingleChar, 0xA5,               0, C_DONTCOUNT},
   496 	{"COPYRIGHT",      EmitSingleByte, '©',  0, C_DONTCOUNT},
   508 	{"COPYRIGHT",      EmitSingleChar, 0xA9,               0, C_DONTCOUNT},
   497 	{"DOWNARROW",      EmitSingleByte, 0xAA, 0, C_DONTCOUNT},
   509 	{"DOWNARROW",      EmitSingleChar, SCC_DOWNARROW,      0, C_DONTCOUNT},
   498 	{"CHECKMARK",      EmitSingleByte, 0xAC, 0, C_DONTCOUNT},
   510 	{"CHECKMARK",      EmitSingleChar, SCC_CHECKMARK,      0, C_DONTCOUNT},
   499 	{"CROSS",          EmitSingleByte, 0xAD, 0, C_DONTCOUNT},
   511 	{"CROSS",          EmitSingleChar, SCC_CROSS,          0, C_DONTCOUNT},
   500 	{"REGISTERED",     EmitSingleByte, '®',  0, C_DONTCOUNT},
   512 	{"REGISTERED",     EmitSingleChar, 0xAE,               0, C_DONTCOUNT},
   501 	{"RIGHTARROW",     EmitSingleByte, 0xAF, 0, C_DONTCOUNT},
   513 	{"RIGHTARROW",     EmitSingleChar, SCC_RIGHTARROW,     0, C_DONTCOUNT},
       
   514 	{"SMALLLEFTARROW", EmitSingleChar, SCC_LESSTHAN,       0, C_DONTCOUNT},
       
   515 	{"SMALLRIGHTARROW",EmitSingleChar, SCC_GREATERTHAN,    0, C_DONTCOUNT},
   502 };
   516 };
   503 
   517 
   504 
   518 
   505 static const CmdStruct *FindCmd(const char *s, int len)
   519 static const CmdStruct *FindCmd(const char *s, int len)
   506 {
   520 {
  1026 	return sum;
  1040 	return sum;
  1027 }
  1041 }
  1028 
  1042 
  1029 static void PutArgidxCommand(void)
  1043 static void PutArgidxCommand(void)
  1030 {
  1044 {
  1031 	PutByte(0x8C);
  1045 	PutUtf8(SCC_ARG_INDEX);
  1032 	PutByte(TranslateArgumentIdx(_cur_argidx));
  1046 	PutByte(TranslateArgumentIdx(_cur_argidx));
  1033 }
  1047 }
  1034 
  1048 
  1035 
  1049 
  1036 static void PutCommandString(const char *str)
  1050 static void PutCommandString(const char *str)
  1050 		}
  1064 		}
  1051 		cs = ParseCommandString(&str, param, &argno, &casei);
  1065 		cs = ParseCommandString(&str, param, &argno, &casei);
  1052 		if (cs == NULL) break;
  1066 		if (cs == NULL) break;
  1053 
  1067 
  1054 		if (casei != -1) {
  1068 		if (casei != -1) {
  1055 			PutByte(0x9D); // {SETCASE}
  1069 			PutUtf8(SCC_SETCASE); // {SETCASE}
  1056 			PutByte(casei);
  1070 			PutByte(casei);
  1057 		}
  1071 		}
  1058 
  1072 
  1059 		// For params that consume values, we need to handle the argindex properly
  1073 		// For params that consume values, we need to handle the argindex properly
  1060 		if (cs->consumes > 0) {
  1074 		if (cs->consumes > 0) {
  1161 
  1175 
  1162 				// Need to output a case-switch.
  1176 				// Need to output a case-switch.
  1163 				// It has this format
  1177 				// It has this format
  1164 				// <0x9E> <NUM CASES> <CASE1> <LEN1> <STRING1> <CASE2> <LEN2> <STRING2> <CASE3> <LEN3> <STRING3> <STRINGDEFAULT>
  1178 				// <0x9E> <NUM CASES> <CASE1> <LEN1> <STRING1> <CASE2> <LEN2> <STRING2> <CASE3> <LEN3> <STRING3> <STRINGDEFAULT>
  1165 				// Each LEN is printed using 2 bytes in big endian order.
  1179 				// Each LEN is printed using 2 bytes in big endian order.
  1166 				PutByte(0x9E);
  1180 				PutUtf8(SCC_SWITCH_CASE);
  1167 				// Count the number of cases
  1181 				// Count the number of cases
  1168 				for (num = 0, c = casep; c; c = c->next) num++;
  1182 				for (num = 0, c = casep; c; c = c->next) num++;
  1169 				PutByte(num);
  1183 				PutByte(num);
  1170 
  1184 
  1171 				// Write each case
  1185 				// Write each case