| 1 | program PAS2HTML; |
| 2 | {$I-} {$B-} |
| 3 | |
| 4 | { PAS2HTML |
| 5 | program pro převod Pascalských zdrojových textů do (X)HTML |
| 6 | (c) 1996, 2009 Pavel Satrapa} |
| 7 | |
| 8 | uses Objects, Dos; |
| 9 | |
| 10 | const Verze = '1.10'; |
| 11 | |
| 12 | JmenoKlicu = 'keyws.def'; |
| 13 | JmenoZnaku = 'chars.def'; |
| 14 | |
| 15 | type PKlicSlovo = ^KlicSlovo; |
| 16 | KlicSlovo = record |
| 17 | Slovo : string[20]; |
| 18 | Dalsi : PKlicSlovo; |
| 19 | end; |
| 20 | |
| 21 | var JmenoZdroje, JmenoSazby : string; |
| 22 | Zdroj, Sazba : Text; |
| 23 | DomaciAdr : string; |
| 24 | Cislovat, {číslovat řádky?} |
| 25 | Komplet, {kompletní WWW stránku?} |
| 26 | Barvit, {barvu pozadí?} |
| 27 | Komentar1, {ve složených závorkách} |
| 28 | Komentar2 : Boolean; {v kulatých s hvězdičkou} |
| 29 | Kodovani : string; {jaké kódování se má vyznačit} |
| 30 | Radek : string; |
| 31 | CisloR : LongInt; |
| 32 | BGColor : string [6]; |
| 33 | Klice : array ['A'..'Z'] of PKlicSlovo; |
| 34 | Znaky : array [Char] of PString; |
| 35 | |
| 36 | |
| 37 | {*************** podpůrné podprogramy ***************} |
| 38 | |
| 39 | procedure Chyba ( Napis : string ); |
| 40 | {vypíše chybové hlášení} |
| 41 | begin |
| 42 | Writeln ( '!!! ERROR: ', Napis ); |
| 43 | end; |
| 44 | |
| 45 | function NaVelka ( Retezec : string ) : string; |
| 46 | {převede řetězec na velká písmena} |
| 47 | {!!! zneužívá toho, že parametr je předáván hodnotou !!!} |
| 48 | var I : Integer; |
| 49 | begin |
| 50 | for I := 1 to Length(Retezec) do |
| 51 | Retezec[I] := UpCase ( Retezec[I] ); |
| 52 | NaVelka := Retezec; |
| 53 | end; |
| 54 | |
| 55 | |
| 56 | {*************** vlastní sazba ***************} |
| 57 | |
| 58 | procedure ZpracujRadek; |
| 59 | {vysází jeden řádek vstupu} |
| 60 | var Pozice : Integer; {index zpracovávaného znaku} |
| 61 | |
| 62 | procedure PisZnak ( Znak : Char ); |
| 63 | {zapíše do výstupu text, odpovídající danému znaku} |
| 64 | begin |
| 65 | Write ( Sazba, Znaky[Znak]^ ); |
| 66 | end; |
| 67 | |
| 68 | procedure PisAPostup; |
| 69 | {vypíše aktuální znak řádku a popojde na další} |
| 70 | begin |
| 71 | PisZnak ( Radek[Pozice] ); |
| 72 | Pozice := Pozice + 1; |
| 73 | end; |
| 74 | |
| 75 | function PristiZnak : Char; |
| 76 | {vydá znak, který v řádku následuje za aktuálním} |
| 77 | begin |
| 78 | if Pozice < Length(Radek) then |
| 79 | PristiZnak := Radek[Pozice+1] |
| 80 | else |
| 81 | PristiZnak := Chr(0); |
| 82 | end; |
| 83 | |
| 84 | procedure ZpracujSlovo; |
| 85 | {načte slovo a vypíše jako identifikátor nebo klíč} |
| 86 | |
| 87 | function JeKlic ( Slovo : string ) : Boolean; |
| 88 | {je 'Slovo' v tabulce klíčových slov ?} |
| 89 | var Pom : PKlicSlovo; |
| 90 | JeToKlic : Boolean; |
| 91 | begin |
| 92 | JeToKlic := False; |
| 93 | Pom := Klice[Slovo[1]]; |
| 94 | while not JeToKlic and (Pom <> nil) do |
| 95 | if Slovo = Pom^.Slovo then JeToKlic := True |
| 96 | else Pom := Pom^.Dalsi; |
| 97 | JeKlic := JeToKlic; |
| 98 | end; |
| 99 | |
| 100 | var Slovo : string; |
| 101 | begin {ZpracujSlovo} |
| 102 | Slovo := ''; |
| 103 | while (Pozice <= Length(Radek)) and |
| 104 | (Radek[Pozice] in ['a'..'z','A'..'Z','_','0'..'9']) do |
| 105 | begin |
| 106 | Slovo := Slovo + Radek[Pozice]; |
| 107 | Pozice := Pozice + 1; |
| 108 | end; |
| 109 | if JeKlic ( NaVelka(Slovo) ) then |
| 110 | Write ( Sazba, '<b>', Slovo, '</b>' ) |
| 111 | else |
| 112 | Write ( Sazba, '<i>', Slovo, '</i>' ); |
| 113 | end; {ZpracujSlovo} |
| 114 | |
| 115 | procedure PreskocMezery; |
| 116 | {vypustí mezery ze začátku řádku} |
| 117 | var PocetMezer, I : Integer; |
| 118 | Dal : Boolean; |
| 119 | begin |
| 120 | I := 1; |
| 121 | Dal := I <= Length ( Radek ); |
| 122 | while Dal do |
| 123 | if Radek[I] <> ' ' then Dal := False |
| 124 | else |
| 125 | begin |
| 126 | I := I + 1; |
| 127 | Dal := I <= Length ( Radek ); |
| 128 | end; |
| 129 | PocetMezer := I - 1; |
| 130 | Delete ( Radek, 1, PocetMezer ); |
| 131 | if Cislovat then |
| 132 | Write ( Sazba, '<tr><td align="right"> <small>', CisloR, |
| 133 | '</small> </td><td>' ) |
| 134 | else |
| 135 | Write ( Sazba, '<tr><td> ' ); |
| 136 | if (Radek <> '') and (PocetMezer > 0) then |
| 137 | begin |
| 138 | Write ( Sazba, '<tt>' ); |
| 139 | for I := 1 to PocetMezer do |
| 140 | Write ( Sazba, ' ' ); |
| 141 | Write ( Sazba, '</tt>' ); |
| 142 | end; |
| 143 | end; |
| 144 | |
| 145 | procedure DokonciKomentar1; |
| 146 | {hledá koncovou složenou závorku, text opisuje} |
| 147 | var Dal : Boolean; |
| 148 | begin |
| 149 | Dal := Pozice <= Length(Radek); |
| 150 | while Dal do |
| 151 | begin |
| 152 | if Radek[Pozice] = '}' then |
| 153 | begin |
| 154 | Komentar1 := False; |
| 155 | Dal := False; |
| 156 | end |
| 157 | else Dal := Pozice < Length(Radek); |
| 158 | PisAPostup; |
| 159 | end; |
| 160 | end; |
| 161 | |
| 162 | procedure DokonciKomentar2; |
| 163 | {hledá koncové '*)', text opisuje} |
| 164 | var Dal : Boolean; |
| 165 | begin |
| 166 | Dal := Pozice <= Length(Radek); |
| 167 | while Dal do |
| 168 | begin |
| 169 | if (Radek[Pozice] = '*') and |
| 170 | (PristiZnak = ')') then |
| 171 | begin |
| 172 | PisAPostup; |
| 173 | Komentar2 := False; |
| 174 | Dal := False; |
| 175 | end |
| 176 | else Dal := Pozice < Length(Radek); |
| 177 | PisAPostup |
| 178 | end; |
| 179 | end; |
| 180 | |
| 181 | procedure DokonciRetezec; |
| 182 | {hledá ukončující apostrof, text opisuje} |
| 183 | begin |
| 184 | repeat |
| 185 | PisAPostup; |
| 186 | until Radek[Pozice]=''''; |
| 187 | PisAPostup; |
| 188 | end; |
| 189 | |
| 190 | begin {ZpracujRadek} |
| 191 | Inc ( CisloR ); |
| 192 | PreskocMezery; |
| 193 | if Radek <> '' then |
| 194 | begin |
| 195 | Pozice := 1; |
| 196 | if Komentar1 then DokonciKomentar1; |
| 197 | if Komentar2 then DokonciKomentar2; |
| 198 | while Pozice <= Length(Radek) do |
| 199 | case Radek[Pozice] of |
| 200 | 'a'..'z','A'..'Z','_' : ZpracujSlovo; |
| 201 | '''' : DokonciRetezec; |
| 202 | '{' : begin |
| 203 | Write ( Sazba, ' ' ); |
| 204 | PisAPostup; |
| 205 | Komentar1 := True; |
| 206 | DokonciKomentar1; |
| 207 | end; |
| 208 | '(' : if PristiZnak <> '*' then PisAPostup |
| 209 | else |
| 210 | begin |
| 211 | Write ( Sazba, ' ' ); |
| 212 | PisAPostup; PisAPostup; |
| 213 | Komentar2 := True; |
| 214 | DokonciKomentar2; |
| 215 | end; |
| 216 | else PisAPostup; |
| 217 | end; |
| 218 | end; |
| 219 | Writeln ( Sazba, ' </td></tr>' ); |
| 220 | if IOResult <> 0 then |
| 221 | Chyba ( 'By write to "' + JmenoSazby + '"' ); |
| 222 | end; {ZpracujRadek} |
| 223 | |
| 224 | |
| 225 | {*************** zahájení, ukončení a spol. ***************} |
| 226 | |
| 227 | procedure ZpracujParametry; |
| 228 | {zpracuje parametry programu} |
| 229 | |
| 230 | procedure NapovedaKonec ( Kod : Integer ); |
| 231 | {návodný text a ukončení programu} |
| 232 | begin |
| 233 | Writeln ( ' PAS2HTML ', Verze ); |
| 234 | Writeln ( '===============' ); |
| 235 | Writeln ( 'Program for typesetting Pascal sources in HTML.' ); |
| 236 | Writeln ( '(c) 1996 Pavel Satrapa' ); |
| 237 | Writeln; |
| 238 | Writeln ( 'Usage: PAS2HTML [input_file [output_file]] [options]' ); |
| 239 | Writeln ( ' default input is standard intput' ); |
| 240 | Writeln ( ' default output is standard output' ); |
| 241 | Writeln ( ' options are:' ); |
| 242 | Writeln ( ' /H print this Help text' ); |
| 243 | Writeln ( ' /N include line Numbers to output' ); |
| 244 | Writeln ( ' /C=RRGGBB bacground color' ); |
| 245 | Writeln ( ' /F full web page' ); |
| 246 | Writeln ( ' /E=encoding announce given encoding (default utf=8, valid only with /F)' ); |
| 247 | Halt (Kod); |
| 248 | end; |
| 249 | |
| 250 | procedure PriradJmeno ( Jmeno : string ); |
| 251 | {přiřazení jména souboru} |
| 252 | begin |
| 253 | if JmenoZdroje = '' then JmenoZdroje := Jmeno |
| 254 | else |
| 255 | if JmenoSazby = '' then JmenoSazby := Jmeno |
| 256 | else |
| 257 | begin |
| 258 | Chyba ( 'Too much parameters "' + Jmeno + '"' ); |
| 259 | NapovedaKonec (1); |
| 260 | end; |
| 261 | end; |
| 262 | |
| 263 | var I : Integer; |
| 264 | Param : string; |
| 265 | begin {ZpracujParametry} |
| 266 | JmenoZdroje := ''; |
| 267 | JmenoSazby := ''; |
| 268 | Cislovat := False; |
| 269 | Komplet := False; |
| 270 | Barvit := False; |
| 271 | Kodovani := 'utf-8'; |
| 272 | for I := 1 to ParamCount do |
| 273 | begin |
| 274 | Param := ParamStr(I); |
| 275 | if Param[1] in ['/','-'] then |
| 276 | case Param[2] of |
| 277 | 'h', 'H', '?' : NapovedaKonec (0); |
| 278 | 'n', 'N' : Cislovat := True; |
| 279 | 'f', 'F' : Komplet := True; |
| 280 | 'e', 'E' : Kodovani := Copy ( Param, 4, Length(Param) - 3 ); |
| 281 | 'c', 'C' : begin |
| 282 | Barvit := True; |
| 283 | BGColor := Copy ( Param, 4, 6 ); |
| 284 | end; |
| 285 | else |
| 286 | begin |
| 287 | Chyba ( 'Bad parameter "' + Param + '"' ); |
| 288 | NapovedaKonec (1); |
| 289 | end; |
| 290 | end |
| 291 | else |
| 292 | PriradJmeno ( Param ); |
| 293 | end; |
| 294 | end; {ZpracujParametry} |
| 295 | |
| 296 | procedure Inicializace; |
| 297 | {počáteční inicializace programu} |
| 298 | |
| 299 | procedure UrciAdresar; |
| 300 | {najde adresář, ve kterém se nachází program} |
| 301 | var |
| 302 | EXEJmeno: PathStr; |
| 303 | Jmeno : NameStr; |
| 304 | Pripona : ExtStr; |
| 305 | begin |
| 306 | EXEJmeno := ParamStr(0); |
| 307 | FSplit(EXEJmeno, DomaciAdr, Jmeno, Pripona); |
| 308 | { if DomaciAdr [ Length(DomaciAdr) ] <> '\' then |
| 309 | DomaciAdr := DomaciAdr + '\'; } |
| 310 | end; |
| 311 | |
| 312 | procedure NactiKlice; |
| 313 | {načte ze souboru klíčová slova a inicalizuje 'Klice'} |
| 314 | |
| 315 | procedure PridejKlic ( KlSlovo : string ); |
| 316 | {přidá 'KlSlovo' do tabulky klíčových slov} |
| 317 | var NovyKlic : PKlicSlovo; |
| 318 | begin |
| 319 | New ( NovyKlic ); |
| 320 | NovyKlic^.Slovo := KlSlovo; |
| 321 | NovyKlic^.Dalsi := Klice[KlSlovo[1]]; |
| 322 | Klice[KlSlovo[1]] := NovyKlic; |
| 323 | end; |
| 324 | |
| 325 | var C : Char; |
| 326 | KlSoub : Text; |
| 327 | Radek : string; |
| 328 | begin {NactiKlice} |
| 329 | for C := 'A' to 'Z' do Klice[C] := nil; |
| 330 | Assign ( KlSoub, DomaciAdr + JmenoKlicu ); |
| 331 | Reset ( KlSoub ); |
| 332 | if IOResult <> 0 then |
| 333 | Chyba ( 'Cannot open keyword file "' + JmenoKlicu + '"' ); |
| 334 | while not Eof(KlSoub) do |
| 335 | begin |
| 336 | Readln ( KlSoub, Radek ); |
| 337 | if Pos ( ' ', Radek ) <> 0 then |
| 338 | Delete ( radek, Pos(' ',Radek), Length(Radek) ); |
| 339 | if Radek <> '' then PridejKlic ( NaVelka(Radek) ); |
| 340 | end; |
| 341 | Close ( KlSoub ); |
| 342 | if IOResult <> 0 then |
| 343 | Chyba ( 'By reading keyword file "' + JmenoKlicu + '"' ); |
| 344 | end; {NactiKlice} |
| 345 | |
| 346 | procedure NactiZnaky; |
| 347 | {načte definice speciálních znaků} |
| 348 | var C : Char; |
| 349 | ZnSoub : Text; |
| 350 | Radek : string; |
| 351 | begin |
| 352 | for C := Chr(0) to Chr(255) do |
| 353 | Znaky[C] := nil; |
| 354 | Assign ( ZnSoub, DomaciAdr + JmenoZnaku ); |
| 355 | Reset ( ZnSoub ); |
| 356 | if IOResult <> 0 then |
| 357 | Chyba ( 'Cannot open char definiton file "' + JmenoZnaku + '"' ); |
| 358 | while not Eof(ZnSoub) do |
| 359 | begin |
| 360 | Readln ( ZnSoub, Radek ); |
| 361 | if Radek <> '' then |
| 362 | begin |
| 363 | C := Radek[1]; |
| 364 | Delete ( Radek, 1, 2 ); |
| 365 | Znaky[C] := NewStr ( Radek ); |
| 366 | end; |
| 367 | end; |
| 368 | Close ( ZnSoub ); |
| 369 | if IOResult <> 0 then |
| 370 | Chyba ( 'By reading char definiton file "' + JmenoZnaku + '"' ); |
| 371 | for C := Chr(0) to Chr(255) do |
| 372 | if Znaky[C] = nil then Znaky[C] := NewStr ( C ); |
| 373 | end; |
| 374 | |
| 375 | begin {Inicializace} |
| 376 | UrciAdresar; |
| 377 | NactiKlice; |
| 378 | NactiZnaky; |
| 379 | Komentar1 := False; |
| 380 | Komentar2 := False; |
| 381 | CisloR := 0; |
| 382 | Assign ( Zdroj, JmenoZdroje ); |
| 383 | Reset ( Zdroj ); |
| 384 | if IOResult <> 0 then |
| 385 | Chyba ( 'Cannot open input file "' + JmenoZdroje + '"' ); |
| 386 | Assign ( Sazba, JmenoSazby ); |
| 387 | Rewrite ( Sazba ); |
| 388 | if IOResult <> 0 then |
| 389 | Chyba ( 'Cannot open output file "' + JmenoSazby + '"' ); |
| 390 | if Komplet then |
| 391 | begin |
| 392 | Writeln ( Sazba, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"'); |
| 393 | Writeln ( Sazba, ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'); |
| 394 | Writeln ( Sazba, '<html xmlns="http://www.w3.org/1999/xhtml">'); |
| 395 | Writeln ( Sazba, '<head>'); |
| 396 | Writeln ( Sazba, '<meta http-equiv="content-type" content="text/html; charset=', |
| 397 | Kodovani, '" />'); |
| 398 | Writeln ( Sazba, '<title>', JmenoZdroje, '</title>'); |
| 399 | Writeln ( Sazba, '</head>'); |
| 400 | Writeln ( Sazba, '<body>'); |
| 401 | Writeln ( Sazba, '<h1>', JmenoZdroje, '</h1>'); |
| 402 | end; |
| 403 | Write ( Sazba, '<table border="0" cellspacing="0" cellpadding="0"' ); |
| 404 | if Barvit then |
| 405 | Write ( Sazba, ' bgcolor="#', BGColor, '"' ); |
| 406 | Writeln ( Sazba, '>' ); |
| 407 | if IOResult <> 0 then |
| 408 | Chyba ( 'By writing to "' + JmenoSazby + '"' ); |
| 409 | end; {Inicializace} |
| 410 | |
| 411 | procedure Konec; |
| 412 | {zakončení programu} |
| 413 | begin |
| 414 | Close ( Zdroj ); |
| 415 | if IOResult <> 0 then |
| 416 | Chyba ( 'Cannot close input "' + JmenoZdroje + '"' ); |
| 417 | Writeln ( Sazba, '</table>' ); |
| 418 | if Komplet then |
| 419 | begin |
| 420 | Writeln ( Sazba, '</body>'); |
| 421 | Writeln ( Sazba, '</html>'); |
| 422 | end; |
| 423 | if IOResult <> 0 then |
| 424 | Chyba ( 'By writing to "' + JmenoSazby + '"' ); |
| 425 | Close ( Sazba ); |
| 426 | if IOResult <> 0 then |
| 427 | Chyba ( 'Cannot close output "' + JmenoSazby + '"' ); |
| 428 | end; |
| 429 | |
| 430 | |
| 431 | {*************** hlavní program ***************} |
| 432 | |
| 433 | begin |
| 434 | ZpracujParametry; |
| 435 | Inicializace; |
| 436 | while not Eof(Zdroj) do |
| 437 | begin |
| 438 | Readln ( Zdroj, Radek ); |
| 439 | if IOResult <> 0 then |
| 440 | Chyba ( 'By reading from "' + JmenoSazby + '"' ); |
| 441 | ZpracujRadek; |
| 442 | end; |
| 443 | Konec; |
| 444 | end. |