Documentation for Toby Speak The software discussed here may be downloaded from http://primepuzzle.com/tc/tobee.zip This documentation is online at http://primepuzzle.com/tc/tobee.tc.html
Tobee Rules!
Tobee Speek iz a language created by Bangor Mykesgirl (aka Amee) on Dec 6
2007. Id all started when she posted wat her kitteh Tobee, hoo loves tah
chase a mouzie and hoo thinks he iz a duckee, "sayd" foah all da world tah
hear.
contact: Lee Bradley
Translation by Toby Speak Version 1.0.5.7 using the twep.dic dictionary.
Oh, I'm sorry! I meant to say that in English, not Toby Speak :-) Toby Speak is a language created by Bangor Belle (aka Amy) on Dec 6 2007. It all started when she posted what her kitten Toby, who loves to chase a mouse and who thinks he is a ducky, "said" for all the world to hear. contact: Lee Bradley This is how it works. Each word in the input file is looked up in an external dictionary and the word, if found, is replaced by the word associated with it. If not found, the word is not changed. The dictionary has the following structure: ... _word1_->~nword1_ _word2_->~nword2_ _word4_->~nword4_ ...Note the underscores, "arrows" and tildes. A file which reads Word2 word4, word3would generate the following: Nword2 nword4, word3Note the retention of case and punctuation and that one of the words is not in the dictionary. The input file may be supplied by the user. If nothing is entered, the default tobee.txt is used. The output is displayed and also written to disc. Two copies are written; one uses the .tbo ("Toby out") extension, the other, an .htm extension. Files can be up to 4500 characters. 1 The program is invoked by running the tiny-c/PC interpreter at a DOS prompt.2 c:\2-7-2008>tinyc.exeand, at the tc> prompt, issuing the command tc>.r tobee.tcYou then invoke the main function of the application via tc>.tobeeYou will be asked for an input file name. You'll be shown the contents of the input file. After hitting any key, the translation will proceed. You'll be shown the translation and, after hitting any key, you'll be returned to the DOS prompt. c:\2-7-2008> Here's a description of the program. Please refer to the source code (http://primepuzzle.com/tc/tobee.tc). /* 1 Needed global variables are declared. /* 2 /* 3 tobee is the main function. A "pinwheel" array is initialized. This will be used to show progress during the translation. ntt is used as a scratch area to hold some text that will be prefixed to the input text. /* 4 Functions hilo and color, which depend on the ansi.sys (or compatible) display driver, are invoked, setting text attributes to "bold" and blue. If you see escape sequences instead, run ANSI.COM before running tinyc.exe. The name and version of this application are announced. Attributes are turned off. /* 6 You are asked for the name of the input file and may optionally specify verbose and / or debug reporting. The debug option is not displayed in the prompt but the code was left in and may still be used. /* 7 loaddic loads a dictionary. If the load is successful and it is the first dictionary (tobee.dic), the input file is read in. If this is successful, a carriage return / line feed is appended to the text (to handle the case of files that don't have a carriage return / line at the end), the text which was put in ntt (see above) is prefixed to the input and ntt is cleared. trantobee is invoked. /* 7a On return, tdf is assigned the next dictionary name (see below) and the cycle repeats. /* 8 /* 9 The dictionary file structure features an initial line which looks like this: [tobee.dic|mar08.dic] This bracketed line is grabbed by the code here. The right bracket (ASCII 93) is used to identify the position of the right hand end of this information. Dictionaries are "chained" in this application; tdfnext is assigned the next dictionary to use (if any). You are given an opportunity to add words to the last dictionary; enter word pairs like still->ztill, dinner->dinnah and then exit by pressing Enter. Words you enter are lower cased. Entries are formatted with underscores and tildes and then added. If words are added to the dictionary, tds (tobee dictionary size) is updated (it is used during dictionary lookup) and then the user is encouraged to send the author an email which contains the words. This message is displayed in bright red. The words are written to the file tobee.msg. There is an audible beep. sak is called. It displays "Strike Any Key ..." on a new line and then waits for you to hit a key. /* 10 trantobee replaces any double spaces with single spaces. sak is called. /* 11 The input file is displayed. /* 12 eof is initialized to 0. If this is the first dictionary, sak is called. Otherwise, you are given the opportunity to press Esc to skip the dictionary just loaded. To make any display during translation easier to watch, the text cursor is turned off (hidden). /* 13 The main loop of the program, doit, is launched (provided you didn't press Esc to skip the dictionary). /* 13a On return, if no vertical line was found in the leading dictionary line, this means we're done translating. In this case, the translation is displayed. Hit a key to proceed. The text cursor is turned back on. We build a "watermark" string to tack onto the end of the output file. This will show what version of Toby Speak did the translating and the name of the last dictionary file that was used. Output file names based on the input file name are built. For example, if the input file is named luna.txt, luna.tbo and luna.htm will be the names generated. These files will have the same content. If the input file has .html tags, you'll want to browse the .htm output file, otherwise, use the .tbo file as a text file. The output string array ntt is written to the output files. On success, you'll be told where to look for the results (in bright white). You'll hear a "tada" type beep and, after hitting any key, you'll be returned to DOS or Windows. If a vertical line was found in the leading dictionary line, the array holding the text to translate is loaded with what's been translated on this pass and the program returns to "line /* 7a". /* 14 Here's how doit works. /* 15 A progress "pinwheel" is displayed for each word as it gets translated (unless verbose or debug is on). /* 16 Two locals are declared. /* 17 The positions of the first carriage return / line feed and space in the input string are determined and placed in nc and n. The place to start looking for these things advances as the translation progresses. /* 18 Debug displays are provided if debug is on. /* 19 A "carriage return switch" is set and n is adjusted when appropriate. The whole issue of when to stick a new line in the output file (to reflect the new lines in the input file) was one of the trickiest parts of this program and this code reflects one of the tweaks that evolved as I worked on getting this ap' to work. /* 20 Both a work string named ws and one named wws are built based on the position of the space (or crlf). When built, they contain the word to be translated next. /* 21 In order to preserve special characters (like .?!,; etc.), we loop thru them all. On finding one of them, we save it in the 1-character array rsc ("remember special character") and break out of the loop. We also stick a null where this special character was - this all done so the look up in the dictionary, which only has words (no punctuation), will work. For example, say our "word" was at the end of a sentence, like blah blah blah foobar.ws and wws would be set to foobar and rsc would have "." in it. In addition, so-called left and right special characters (the double quote and the left / right parenthesis) are handled here. /* 22 Next, a little work string called fus (I always use foobar-like names when needing scratch variables and in this case came up with fus - the us for "underscore") is loaded with our word flanked on the left and right with underscores and then stuck back in wws. /* 23 Both wws and ws are displayed if debugging. If our word was "and" we would have ws containing "and" and wws containing "_and_". The whole idea here is we pad our word with a character which seldom appears in standard text files and then look for the corresponding padded word in the "left side" of our dictionary pairs. This idea is used to get around the fact that, for example, "and" is part of "sand" but "_and_" is not part of "_sand_". /* 24 Because we're interested in preserving the case (upper and lower) of our text, we bump the first character up by the value of an ASCII space, which makes it lower case, when it is found to be an upper case letter and we also set a cap switch. This is all done because our dictionary is strictly a lower case file and we need lookups to work. /* 25 Finally, we look for our "_and_" in the dictionary. /* 26 If we don't find it, we fix the case of the original word when needed and then drop down to "line /* 26h". /* 26a Otherwise, we've found "_and_" and we need to see what its "translation" is in the dictionary. The dictionary has _and_->~an_We advance dp, the pointer in the dictionary, past the word and the "->~" so now we're looking at the "a" of "an_". We then loop, looking for the trailing underscore and load ws with "an". /* 26g Special logic is needed to support the possibility that our translated word might not be a "word" for which case has meaning. For example, say we had "To be or not to be"and the word "To" had a dictionary entry _to_->~2_Since "To" is an upper case word, our cap switch will be set. As we are about to tack the translation onto our target string, we don't want to upper case the "2" because there is no such thing as an upper case "2". /* 26h Finally, we tack the translation, prefixed and postfixed with any special left and right characters and any remembered special character and a space, onto our new tobee text. If the word was found in the dictionary and verbose is on, after stripping any of the special characters, the word and its translation are displayed. /* 27 We now are ready to bump the pointer which tells us where we are in the input string (tt) by using n which tells us where the space or carriage return was. Note the -1 in tt=tt+n-1The index function is tricky in that it returns one more than what you might think it should. I usually find I have to use what I think is correct and then mess with it by adding or subtracting 1 till I get it right! /* 27a An important but subtle adjustment is made to the pointer if we're dealing with an end of line situation (ie. carriage return switch is set). The whole issue of the 2-character crlf case was tricky to get right. Further adjustments to the pointer and to the output string involving carriage returns are made when needed. /* 27c Finally, we test to see if we're pointing at a null which signals we're done and if we are we set the eof switch to 1. Once doit is done, we return to where it all started, namely "line /* 13a". |