Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1186 | savelij | 1 | /* asmsub.c */ |
| 2 | /*****************************************************************************/ |
||
| 3 | /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */ |
||
| 4 | /* */ |
||
| 5 | /* AS-Portierung */ |
||
| 6 | /* */ |
||
| 7 | /* Unterfunktionen, vermischtes */ |
||
| 8 | /* */ |
||
| 9 | /*****************************************************************************/ |
||
| 10 | |||
| 11 | #include "stdinc.h" |
||
| 12 | #include <string.h> |
||
| 13 | #include <ctype.h> |
||
| 14 | #include <stdarg.h> |
||
| 15 | #include <float.h> |
||
| 16 | |||
| 17 | #include "version.h" |
||
| 18 | #include "be_le.h" |
||
| 19 | #include "stdhandl.h" |
||
| 20 | #include "console.h" |
||
| 21 | #include "nls.h" |
||
| 22 | #include "chardefs.h" |
||
| 23 | #include "nlmessages.h" |
||
| 24 | #include "cmdarg.h" |
||
| 25 | #include "as.rsc" |
||
| 26 | #include "strutil.h" |
||
| 27 | #include "stringlists.h" |
||
| 28 | #include "chunks.h" |
||
| 29 | #include "ioerrs.h" |
||
| 30 | #include "intformat.h" |
||
| 31 | #include "errmsg.h" |
||
| 32 | #include "asmdef.h" |
||
| 33 | #include "asmpars.h" |
||
| 34 | #include "asmdebug.h" |
||
| 35 | #include "asmlist.h" |
||
| 36 | #include "as.h" |
||
| 37 | |||
| 38 | #include "asmsub.h" |
||
| 39 | |||
| 40 | |||
| 41 | #ifdef __TURBOC__ |
||
| 42 | #ifdef __DPMI16__ |
||
| 43 | #define STKSIZE 32768 |
||
| 44 | #else |
||
| 45 | #define STKSIZE 49152 |
||
| 46 | #endif |
||
| 47 | #endif |
||
| 48 | |||
| 49 | #define VALID_S1 1 |
||
| 50 | #define VALID_SN 2 |
||
| 51 | #define VALID_M1 4 |
||
| 52 | #define VALID_MN 8 |
||
| 53 | |||
| 54 | static StringList CopyrightList, OutList, ShareOutList, ListOutList; |
||
| 55 | |||
| 56 | static LongWord StartStack, MinStack, LowStack; |
||
| 57 | |||
| 58 | static unsigned ValidSymCharLen; |
||
| 59 | static Byte *ValidSymChar; |
||
| 60 | |||
| 61 | /****************************************************************************/ |
||
| 62 | /* Modulinitialisierung */ |
||
| 63 | |||
| 64 | void AsmSubPassInit(void) |
||
| 65 | { |
||
| 66 | PageLength = 60; |
||
| 67 | PageWidth = 0; |
||
| 68 | } |
||
| 69 | |||
| 70 | /****************************************************************************/ |
||
| 71 | /* Copyrightlistenverwaltung */ |
||
| 72 | |||
| 73 | void AddCopyright(const char *NewLine) |
||
| 74 | { |
||
| 75 | AddStringListLast(&CopyrightList, NewLine); |
||
| 76 | } |
||
| 77 | |||
| 78 | void WriteCopyrights(void(*PrintProc)(const char *)) |
||
| 79 | { |
||
| 80 | StringRecPtr Lauf; |
||
| 81 | const char *p_line; |
||
| 82 | |||
| 83 | for (p_line = GetStringListFirst(CopyrightList, &Lauf); |
||
| 84 | p_line; p_line = GetStringListNext(&Lauf)) |
||
| 85 | PrintProc(p_line); |
||
| 86 | } |
||
| 87 | |||
| 88 | /*!------------------------------------------------------------------------ |
||
| 89 | * \fn QuotMultPosQualify(const char *s, const char *pSearch, as_qualify_quote_fnc_t QualifyQuoteFnc) |
||
| 90 | * \brief find first occurence in non-quoted areas of string |
||
| 91 | * \param s string to search in |
||
| 92 | * \param pSearch search test function (returns 0 for match) |
||
| 93 | * \param QualifyQuoteFnc checks whether single quote actually begins quoted area |
||
| 94 | * \return first occurence or NULL if not found |
||
| 95 | * ------------------------------------------------------------------------ */ |
||
| 96 | |||
| 97 | typedef struct |
||
| 98 | { |
||
| 99 | as_quoted_iterator_cb_data_t data; |
||
| 100 | ShortInt brack, ang_brack; |
||
| 101 | const char *p_result; |
||
| 102 | int (*search_fnc)(const char*, const char*); |
||
| 103 | const char *p_search; |
||
| 104 | } quot_search_cb_data; |
||
| 105 | |||
| 106 | static int quot_search_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data) |
||
| 107 | { |
||
| 108 | quot_search_cb_data *p_data = (quot_search_cb_data*)p_cb_data; |
||
| 109 | |||
| 110 | if (!p_data->brack && !p_data->ang_brack && !p_data->search_fnc(p_pos, p_data->p_search)) |
||
| 111 | { |
||
| 112 | p_data->p_result = p_pos; |
||
| 113 | return -1; |
||
| 114 | } |
||
| 115 | |||
| 116 | switch (*p_pos) |
||
| 117 | { |
||
| 118 | case '(': |
||
| 119 | if (!p_data->ang_brack) |
||
| 120 | p_data->brack++; |
||
| 121 | break; |
||
| 122 | case ')': |
||
| 123 | if (!p_data->ang_brack) |
||
| 124 | p_data->brack--; |
||
| 125 | break; |
||
| 126 | case '[': |
||
| 127 | if (!p_data->brack) |
||
| 128 | p_data->ang_brack++; |
||
| 129 | break; |
||
| 130 | case ']': |
||
| 131 | if (!p_data->brack) |
||
| 132 | p_data->ang_brack--; |
||
| 133 | break; |
||
| 134 | } |
||
| 135 | |||
| 136 | return 0; |
||
| 137 | } |
||
| 138 | |||
| 139 | static char *QuotPosCore(const char *s, int (*SearchFnc)(const char*, const char*), const char *pSearch, as_qualify_quote_fnc_t QualifyQuoteFnc) |
||
| 140 | { |
||
| 141 | quot_search_cb_data data; |
||
| 142 | |||
| 143 | data.data.qualify_quote = QualifyQuoteFnc; |
||
| 144 | data.data.callback_before = True; |
||
| 145 | data.brack = data.ang_brack = 0; |
||
| 146 | data.p_result = NULL; |
||
| 147 | data.search_fnc = SearchFnc; |
||
| 148 | data.p_search = pSearch; |
||
| 149 | |||
| 150 | as_iterate_str_quoted(s, quot_search_cb, &data.data); |
||
| 151 | return (char*)data.p_result; |
||
| 152 | } |
||
| 153 | |||
| 154 | /*!------------------------------------------------------------------------ |
||
| 155 | * \fn QuotMultPosQualify(const char *s, char Zeichen, as_qualify_quote_fnc_t QualifyQuoteFnc) |
||
| 156 | * \brief find first occurence of characters in non-quoted areas of string |
||
| 157 | * \param s string to search in |
||
| 158 | * \param Zeichen characters to search for |
||
| 159 | * \param QualifyQuoteFnc checks whether single quote actually begins quoted area |
||
| 160 | * \return first occurence or NULL if not found |
||
| 161 | * ------------------------------------------------------------------------ */ |
||
| 162 | |||
| 163 | static int SearchMultChar(const char *pPos, const char *pSearch) |
||
| 164 | { |
||
| 165 | return !strchr(pSearch, *pPos); |
||
| 166 | } |
||
| 167 | |||
| 168 | char *QuotMultPosQualify(const char *s, const char *pSearch, as_qualify_quote_fnc_t QualifyQuoteFnc) |
||
| 169 | { |
||
| 170 | return QuotPosCore(s, SearchMultChar, pSearch, QualifyQuoteFnc); |
||
| 171 | } |
||
| 172 | |||
| 173 | /*!------------------------------------------------------------------------ |
||
| 174 | * \fn QuotPosQualify(const char *s, char Zeichen, as_qualify_quote_fnc_t QualifyQuoteFnc) |
||
| 175 | * \brief find first occurence of character in non-quoted areas of string |
||
| 176 | * \param s string to search in |
||
| 177 | * \param Zeichen character to search for |
||
| 178 | * \param QualifyQuoteFnc checks whether single quote actually begins quoted area |
||
| 179 | * \return first occurence or NULL if not found |
||
| 180 | * ------------------------------------------------------------------------ */ |
||
| 181 | |||
| 182 | static int SearchSingleChar(const char *pPos, const char *pSearch) |
||
| 183 | { |
||
| 184 | return ((int)*pSearch) - ((int)*pPos); |
||
| 185 | } |
||
| 186 | |||
| 187 | char *QuotPosQualify(const char *s, char Zeichen, as_qualify_quote_fnc_t QualifyQuoteFnc) |
||
| 188 | { |
||
| 189 | return QuotPosCore(s, SearchSingleChar, &Zeichen, QualifyQuoteFnc); |
||
| 190 | } |
||
| 191 | |||
| 192 | /*!------------------------------------------------------------------------ |
||
| 193 | * \fn QuotSMultPosQualify(const char *s, const char *pStrs, as_qualify_quote_fnc_t QualifyQuoteFnc) |
||
| 194 | * \brief find first occurence of strings in non-quoted areas of string |
||
| 195 | * \param s string to search in |
||
| 196 | * \param pStrs strings to search for (continuous list, terminated by empty string) |
||
| 197 | * \param QualifyQuoteFnc checks whether single quote actually begins quoted area |
||
| 198 | * \return first occurence or NULL if not found |
||
| 199 | * ------------------------------------------------------------------------ */ |
||
| 200 | |||
| 201 | static int SearchMultString(const char *pPos, const char *pSearch) |
||
| 202 | { |
||
| 203 | int len; |
||
| 204 | |||
| 205 | while (True) |
||
| 206 | { |
||
| 207 | if (!(len = strlen(pSearch))) |
||
| 208 | return 1; |
||
| 209 | if (!strncmp(pPos, pSearch, len)) |
||
| 210 | return 0; |
||
| 211 | pSearch += len + 1; |
||
| 212 | } |
||
| 213 | } |
||
| 214 | |||
| 215 | char *QuotSMultPosQualify(const char *s, const char *pStrs, as_qualify_quote_fnc_t QualifyQuoteFnc) |
||
| 216 | { |
||
| 217 | return QuotPosCore(s, SearchMultString, pStrs, QualifyQuoteFnc); |
||
| 218 | } |
||
| 219 | |||
| 220 | /*!------------------------------------------------------------------------ |
||
| 221 | * \fn RQuotPos(char *s, char Zeichen) |
||
| 222 | * \brief find last occurence of character, skipping quoted/parenthized parts |
||
| 223 | * \param s string to search |
||
| 224 | * \param Zeichen character to search for |
||
| 225 | * \return last occurence or NULL if not found at all |
||
| 226 | * ------------------------------------------------------------------------ */ |
||
| 227 | |||
| 228 | /* NOTE: Though we search for the last occurence, it is not wise to search |
||
| 229 | the string in backward direction. Character escaping can only be tracked |
||
| 230 | correctly and unambiguously if we traverse the string in forward order. |
||
| 231 | So when we found an occurence, continue to search for a later one: */ |
||
| 232 | |||
| 233 | typedef struct |
||
| 234 | { |
||
| 235 | as_quoted_iterator_cb_data_t data; |
||
| 236 | ShortInt brack, ang_brack; |
||
| 237 | const char *p_result; |
||
| 238 | char search; |
||
| 239 | } rquot_search_cb_data; |
||
| 240 | |||
| 241 | static int rquot_search_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data) |
||
| 242 | { |
||
| 243 | rquot_search_cb_data *p_data = (rquot_search_cb_data*)p_cb_data; |
||
| 244 | |||
| 245 | if (!p_data->brack && !p_data->ang_brack && (*p_pos == p_data->search)) |
||
| 246 | p_data->p_result = p_pos; |
||
| 247 | |||
| 248 | else switch (*p_pos) |
||
| 249 | { |
||
| 250 | case '(': |
||
| 251 | if (!p_data->ang_brack) |
||
| 252 | p_data->brack++; |
||
| 253 | break; |
||
| 254 | case ')': |
||
| 255 | if (!p_data->ang_brack) |
||
| 256 | p_data->brack--; |
||
| 257 | break; |
||
| 258 | case '[': |
||
| 259 | if (!p_data->brack) |
||
| 260 | p_data->ang_brack++; |
||
| 261 | break; |
||
| 262 | case ']': |
||
| 263 | if (!p_data->brack) |
||
| 264 | p_data->ang_brack--; |
||
| 265 | break; |
||
| 266 | } |
||
| 267 | |||
| 268 | return 0; |
||
| 269 | } |
||
| 270 | |||
| 271 | char *RQuotPos(char *s, char Zeichen) |
||
| 272 | { |
||
| 273 | rquot_search_cb_data data; |
||
| 274 | |||
| 275 | data.data.qualify_quote = QualifyQuote; |
||
| 276 | data.data.callback_before = True; |
||
| 277 | data.brack = data.ang_brack = 0; |
||
| 278 | data.p_result = NULL; |
||
| 279 | data.search = Zeichen; |
||
| 280 | |||
| 281 | as_iterate_str_quoted(s, rquot_search_cb, &data.data); |
||
| 282 | return (char*)data.p_result; |
||
| 283 | } |
||
| 284 | |||
| 285 | /*!------------------------------------------------------------------------ |
||
| 286 | * \fn CopyNoBlanks(char *pDest, const char *pSrc, size_t MaxLen) |
||
| 287 | * \brief copy string, excluding spaces in non-quoted areas |
||
| 288 | * \param pDest destination buffer |
||
| 289 | * \param pSrc copy source |
||
| 290 | * \param MaxLen capacity of dest buffer |
||
| 291 | * \return # of copied characters, excluding NUL |
||
| 292 | * ------------------------------------------------------------------------ */ |
||
| 293 | |||
| 294 | typedef struct |
||
| 295 | { |
||
| 296 | as_quoted_iterator_cb_data_t data; |
||
| 297 | char *p_dest; |
||
| 298 | size_t rem_cap, cnt; |
||
| 299 | } copy_cb_data_t; |
||
| 300 | |||
| 301 | static int copy_no_blanks_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data) |
||
| 302 | { |
||
| 303 | copy_cb_data_t *p_data = (copy_cb_data_t*)p_cb_data; |
||
| 304 | |||
| 305 | /* leave space for NUL */ |
||
| 306 | |||
| 307 | if ((p_cb_data->in_single_quote || p_cb_data->in_double_quote || !as_isspace(*p_pos)) && (p_data->rem_cap > 1)) |
||
| 308 | { |
||
| 309 | *(p_data->p_dest++) = *p_pos; |
||
| 310 | p_data->rem_cap--; |
||
| 311 | p_data->cnt++; |
||
| 312 | } |
||
| 313 | return 0; |
||
| 314 | } |
||
| 315 | |||
| 316 | int CopyNoBlanks(char *pDest, const char *pSrc, size_t MaxLen) |
||
| 317 | { |
||
| 318 | copy_cb_data_t data; |
||
| 319 | |||
| 320 | data.data.qualify_quote = NULL; |
||
| 321 | data.data.callback_before = True; |
||
| 322 | data.p_dest = pDest; |
||
| 323 | data.rem_cap = MaxLen; |
||
| 324 | data.cnt = 0; |
||
| 325 | |||
| 326 | as_iterate_str(pSrc, copy_no_blanks_cb, &data.data); |
||
| 327 | if (data.rem_cap) |
||
| 328 | *(data.p_dest) = '\0'; |
||
| 329 | |||
| 330 | return data.cnt; |
||
| 331 | } |
||
| 332 | |||
| 333 | /*!------------------------------------------------------------------------ |
||
| 334 | * \fn KillBlanks(char *s) |
||
| 335 | * \brief Delete all spaces in non-quoted areas from string |
||
| 336 | * \param s string to process |
||
| 337 | * ------------------------------------------------------------------------ */ |
||
| 338 | |||
| 339 | void KillBlanks(char *s) |
||
| 340 | { |
||
| 341 | CopyNoBlanks(s, s, 65535); /* SIZE_MAX */ |
||
| 342 | } |
||
| 343 | |||
| 344 | /*--------------------------------------------------------------------------*/ |
||
| 345 | /* ermittelt das erste (nicht-) Leerzeichen in einem String */ |
||
| 346 | |||
| 347 | char *FirstBlank(const char *s) |
||
| 348 | { |
||
| 349 | const char *h, *Min = NULL; |
||
| 350 | |||
| 351 | h = strchr(s, ' '); |
||
| 352 | if (h) |
||
| 353 | if ((!Min) || (h < Min)) |
||
| 354 | Min = h; |
||
| 355 | h = strchr(s, Char_HT); |
||
| 356 | if (h) |
||
| 357 | if ((!Min) || (h < Min)) |
||
| 358 | Min = h; |
||
| 359 | return (char*)Min; |
||
| 360 | } |
||
| 361 | |||
| 362 | /*--------------------------------------------------------------------------*/ |
||
| 363 | /* einen String in zwei Teile zerlegen */ |
||
| 364 | |||
| 365 | void SplitString(char *Source, char *Left, char *Right, char *Trenner) |
||
| 366 | { |
||
| 367 | char Save; |
||
| 368 | LongInt slen = strlen(Source); |
||
| 369 | |||
| 370 | if ((!Trenner) || (Trenner >= Source + slen)) |
||
| 371 | Trenner = Source + slen; |
||
| 372 | Save = (*Trenner); |
||
| 373 | *Trenner = '\0'; |
||
| 374 | strmov(Left, Source); |
||
| 375 | *Trenner = Save; |
||
| 376 | if (Trenner >= Source + slen) |
||
| 377 | *Right = '\0'; |
||
| 378 | else |
||
| 379 | strmov(Right, Trenner + 1); |
||
| 380 | } |
||
| 381 | |||
| 382 | /*!------------------------------------------------------------------------ |
||
| 383 | * \fn UpString(char *s) |
||
| 384 | * \brief convert string to upper case, excluding quoted areas |
||
| 385 | * \param s string to convert |
||
| 386 | * ------------------------------------------------------------------------ */ |
||
| 387 | |||
| 388 | static int upstring_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data) |
||
| 389 | { |
||
| 390 | UNUSED(p_cb_data); |
||
| 391 | *((char*)p_pos) = UpCaseTable[(int)*p_pos]; |
||
| 392 | return 0; |
||
| 393 | } |
||
| 394 | |||
| 395 | void UpString(char *s) |
||
| 396 | { |
||
| 397 | as_quoted_iterator_cb_data_t data; |
||
| 398 | |||
| 399 | data.qualify_quote = QualifyQuote; |
||
| 400 | data.callback_before = False; |
||
| 401 | |||
| 402 | as_iterate_str_quoted(s, upstring_cb, &data); |
||
| 403 | } |
||
| 404 | |||
| 405 | /*!------------------------------------------------------------------------ |
||
| 406 | * \fn MatchChars(const char *pStr, const char *pPattern, ...) |
||
| 407 | * \brief see if beginning of string matches given pattern |
||
| 408 | * \param pStr string to check |
||
| 409 | * \param pPattern expected pattern |
||
| 410 | * \return * to character following match or NULL if no match |
||
| 411 | * ------------------------------------------------------------------------ */ |
||
| 412 | |||
| 413 | char *MatchChars(const char *pStr, const char *pPattern, ...) |
||
| 414 | { |
||
| 415 | va_list ap; |
||
| 416 | char *pResult = NULL; |
||
| 417 | |||
| 418 | va_start(ap, pPattern); |
||
| 419 | for (; *pPattern; pPattern++) |
||
| 420 | switch (*pPattern) |
||
| 421 | { |
||
| 422 | /* single space in pattern matches arbitrary # of spaces in string */ |
||
| 423 | case ' ': |
||
| 424 | for (; as_isspace(*pStr); pStr++); |
||
| 425 | break; |
||
| 426 | case '?': |
||
| 427 | { |
||
| 428 | const char *pPatternStr = va_arg(ap, const char*); |
||
| 429 | char *pSave = va_arg(ap, char*); |
||
| 430 | |||
| 431 | if (!strchr(pPatternStr, as_toupper(*pStr))) |
||
| 432 | goto func_exit; |
||
| 433 | if (pSave) |
||
| 434 | *pSave = *pStr; |
||
| 435 | pStr++; |
||
| 436 | break; |
||
| 437 | } |
||
| 438 | default: |
||
| 439 | if (as_toupper(*pStr) != as_toupper(*pPattern)) |
||
| 440 | goto func_exit; |
||
| 441 | pStr++; |
||
| 442 | } |
||
| 443 | pResult = (char*)pStr; |
||
| 444 | func_exit: |
||
| 445 | va_end(ap); |
||
| 446 | return pResult; |
||
| 447 | } |
||
| 448 | |||
| 449 | /*!------------------------------------------------------------------------ |
||
| 450 | * \fn MatchCharsRev(const char *pStr, const char *pPattern, ...) |
||
| 451 | * \brief see if end of string matches given pattern |
||
| 452 | * \param pStr string to check |
||
| 453 | * \param pPattern expected pattern |
||
| 454 | * \return * to trailing string matching pattern or NULL if no match |
||
| 455 | * ------------------------------------------------------------------------ */ |
||
| 456 | |||
| 457 | char *MatchCharsRev(const char *pStr, const char *pPattern, ...) |
||
| 458 | { |
||
| 459 | va_list ap; |
||
| 460 | char *pResult = NULL; |
||
| 461 | const char *pPatternRun = pPattern + strlen(pPattern) - 1, |
||
| 462 | *pStrRun = pStr + strlen(pStr) - 1; |
||
| 463 | |||
| 464 | va_start(ap, pPattern); |
||
| 465 | for (; pPatternRun >= pPattern; pPatternRun--) |
||
| 466 | switch (*pPatternRun) |
||
| 467 | { |
||
| 468 | /* single space in pattern matches arbitrary # of spaces in string */ |
||
| 469 | case ' ': |
||
| 470 | for (; (pStrRun >= pStr) && as_isspace(*pStrRun); pStrRun--); |
||
| 471 | break; |
||
| 472 | case '?': |
||
| 473 | { |
||
| 474 | const char *pPatternStr = va_arg(ap, const char*); |
||
| 475 | char *pSave = va_arg(ap, char*); |
||
| 476 | |||
| 477 | if (!strchr(pPatternStr, as_toupper(*pStrRun))) |
||
| 478 | goto func_exit; |
||
| 479 | if (pSave) |
||
| 480 | *pSave = *pStrRun; |
||
| 481 | pStrRun--; |
||
| 482 | break; |
||
| 483 | } |
||
| 484 | default: |
||
| 485 | if ((pStrRun < pStr) || (as_toupper(*pStrRun) != as_toupper(*pPatternRun))) |
||
| 486 | goto func_exit; |
||
| 487 | pStrRun--; |
||
| 488 | } |
||
| 489 | pResult = (char*)(pStrRun + 1); |
||
| 490 | func_exit: |
||
| 491 | va_end(ap); |
||
| 492 | return pResult; |
||
| 493 | } |
||
| 494 | |||
| 495 | /*!------------------------------------------------------------------------ |
||
| 496 | * \fn FindClosingParenthese(const char *pStr) |
||
| 497 | * \brief find matching closing parenthese |
||
| 498 | * \param pStr * to string right after opening parenthese |
||
| 499 | * \return * to closing parenthese or NULL |
||
| 500 | * ------------------------------------------------------------------------ */ |
||
| 501 | |||
| 502 | typedef struct |
||
| 503 | { |
||
| 504 | as_quoted_iterator_cb_data_t data; |
||
| 505 | int nest; |
||
| 506 | const char *p_ret; |
||
| 507 | } close_par_cb_data_t; |
||
| 508 | |||
| 509 | static int close_par_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data) |
||
| 510 | { |
||
| 511 | close_par_cb_data_t *p_data = (close_par_cb_data_t*)p_cb_data; |
||
| 512 | |||
| 513 | switch(*p_pos) |
||
| 514 | { |
||
| 515 | case '(': |
||
| 516 | p_data->nest++; |
||
| 517 | break; |
||
| 518 | case ')': |
||
| 519 | if (!--p_data->nest) |
||
| 520 | { |
||
| 521 | p_data->p_ret = p_pos; |
||
| 522 | return -1; |
||
| 523 | } |
||
| 524 | break; |
||
| 525 | } |
||
| 526 | return 0; |
||
| 527 | } |
||
| 528 | |||
| 529 | char *FindClosingParenthese(const char *pStr) |
||
| 530 | { |
||
| 531 | close_par_cb_data_t data; |
||
| 532 | |||
| 533 | data.data.callback_before = False; |
||
| 534 | data.data.qualify_quote = QualifyQuote; |
||
| 535 | data.nest = 1; |
||
| 536 | data.p_ret = NULL; |
||
| 537 | |||
| 538 | as_iterate_str_quoted(pStr, close_par_cb, &data.data); |
||
| 539 | |||
| 540 | return (char*)data.p_ret; |
||
| 541 | } |
||
| 542 | |||
| 543 | /*!------------------------------------------------------------------------ |
||
| 544 | * \fn FindOpeningParenthese(const char *pStrBegin, const char *pStrEnd, const char Bracks[2]) |
||
| 545 | * \brief find matching opening parenthese in string |
||
| 546 | * \param pStrBegin start of string |
||
| 547 | * \param pStrEnd end of string, preceding closing parenthese in question |
||
| 548 | * \param Bracks opening & closing parenthese |
||
| 549 | * \return * to opening parenthese or NULL if not found |
||
| 550 | * ------------------------------------------------------------------------ */ |
||
| 551 | |||
| 552 | typedef struct |
||
| 553 | { |
||
| 554 | as_quoted_iterator_cb_data_t data; |
||
| 555 | int nest; |
||
| 556 | const char *p_str_end; |
||
| 557 | const char *p_ret; |
||
| 558 | const char *p_bracks; |
||
| 559 | } open_par_cb_data_t; |
||
| 560 | |||
| 561 | static int open_par_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data) |
||
| 562 | { |
||
| 563 | open_par_cb_data_t *p_data = (open_par_cb_data_t*)p_cb_data; |
||
| 564 | |||
| 565 | if (*p_pos == p_data->p_bracks[0]) |
||
| 566 | { |
||
| 567 | if (!p_data->nest) |
||
| 568 | p_data->p_ret = p_pos; |
||
| 569 | p_data->nest++; |
||
| 570 | } |
||
| 571 | else if (*p_pos == p_data->p_bracks[1]) |
||
| 572 | p_data->nest--; |
||
| 573 | |||
| 574 | /* We are interested in the opening parenthese that is nearest to the closing |
||
| 575 | one and on same level, so continue searching: */ |
||
| 576 | |||
| 577 | return ((p_pos + 1) < p_data->p_str_end) ? 0 : -1; |
||
| 578 | } |
||
| 579 | |||
| 580 | char *FindOpeningParenthese(const char *pStrBegin, const char *pStrEnd, const char Bracks[2]) |
||
| 581 | { |
||
| 582 | open_par_cb_data_t data; |
||
| 583 | |||
| 584 | data.data.callback_before = False; |
||
| 585 | data.data.qualify_quote = QualifyQuote; |
||
| 586 | data.nest = 0; |
||
| 587 | data.p_ret = NULL; |
||
| 588 | data.p_bracks = Bracks; |
||
| 589 | data.p_str_end = pStrEnd; |
||
| 590 | |||
| 591 | as_iterate_str_quoted(pStrBegin, open_par_cb, &data.data); |
||
| 592 | |||
| 593 | return (char*)data.p_ret; |
||
| 594 | } |
||
| 595 | |||
| 596 | /****************************************************************************/ |
||
| 597 | |||
| 598 | ShortInt StrCaseCmp(const char *s1, const char *s2, LongInt Hand1, LongInt Hand2) |
||
| 599 | { |
||
| 600 | int tmp; |
||
| 601 | |||
| 602 | tmp = as_toupper(*s1) - as_toupper(*s2); |
||
| 603 | if (!tmp) |
||
| 604 | tmp = as_strcasecmp(s1, s2); |
||
| 605 | if (!tmp) |
||
| 606 | tmp = Hand1 - Hand2; |
||
| 607 | if (tmp < 0) |
||
| 608 | return -1; |
||
| 609 | if (tmp > 0) |
||
| 610 | return 1; |
||
| 611 | return 0; |
||
| 612 | } |
||
| 613 | |||
| 614 | /****************************************************************************/ |
||
| 615 | /* an einen Dateinamen eine Endung anhaengen */ |
||
| 616 | |||
| 617 | Boolean AddSuffix(char *s, const char *Suff) |
||
| 618 | { |
||
| 619 | char *p, *z, *Part; |
||
| 620 | |||
| 621 | p = NULL; |
||
| 622 | for (z = s; *z != '\0'; z++) |
||
| 623 | if (*z == PATHSEP) |
||
| 624 | p = z; |
||
| 625 | Part = p ? p : s; |
||
| 626 | if (!strchr(Part, '.')) |
||
| 627 | { |
||
| 628 | strmaxcat(s, Suff, STRINGSIZE); |
||
| 629 | return True; |
||
| 630 | } |
||
| 631 | else |
||
| 632 | return False; |
||
| 633 | } |
||
| 634 | |||
| 635 | |||
| 636 | /*--------------------------------------------------------------------------*/ |
||
| 637 | /* von einem Dateinamen die Endung loeschen */ |
||
| 638 | |||
| 639 | void KillSuffix(char *s) |
||
| 640 | { |
||
| 641 | char *p, *z, *Part; |
||
| 642 | |||
| 643 | p = NULL; |
||
| 644 | for (z = s; *z != '\0'; z++) |
||
| 645 | if (*z == PATHSEP) |
||
| 646 | p = z; |
||
| 647 | Part = p ? p : s; |
||
| 648 | Part = strchr(Part, '.'); |
||
| 649 | if (Part) |
||
| 650 | *Part = '\0'; |
||
| 651 | } |
||
| 652 | |||
| 653 | /*--------------------------------------------------------------------------*/ |
||
| 654 | /* Pfadanteil (Laufwerk+Verzeichnis) von einem Dateinamen abspalten */ |
||
| 655 | |||
| 656 | char *PathPart(char *Name) |
||
| 657 | { |
||
| 658 | static String s; |
||
| 659 | char *p; |
||
| 660 | |||
| 661 | strmaxcpy(s, Name, STRINGSIZE); |
||
| 662 | |||
| 663 | p = strrchr(Name, PATHSEP); |
||
| 664 | #ifdef DRSEP |
||
| 665 | if (!p) |
||
| 666 | p = strrchr(Name, DRSEP); |
||
| 667 | #endif |
||
| 668 | |||
| 669 | if (!p) |
||
| 670 | *s = '\0'; |
||
| 671 | else |
||
| 672 | s[1] = '\0'; |
||
| 673 | |||
| 674 | return s; |
||
| 675 | } |
||
| 676 | |||
| 677 | /*--------------------------------------------------------------------------*/ |
||
| 678 | /* Namensanteil von einem Dateinamen abspalten */ |
||
| 679 | |||
| 680 | const char *NamePart(const char *Name) |
||
| 681 | { |
||
| 682 | const char *p = strrchr(Name, PATHSEP); |
||
| 683 | |||
| 684 | #ifdef DRSEP |
||
| 685 | if (!p) |
||
| 686 | p = strrchr(Name, DRSEP); |
||
| 687 | #endif |
||
| 688 | |||
| 689 | return p ? p + 1 : Name; |
||
| 690 | } |
||
| 691 | |||
| 692 | /****************************************************************************/ |
||
| 693 | /* eine Gleitkommazahl in einen String umwandeln */ |
||
| 694 | |||
| 695 | void FloatString(char *pDest, size_t DestSize, as_float_t f) |
||
| 696 | { |
||
| 697 | #define MaxLen (3 + AS_FLOAT_DIG) |
||
| 698 | char *p, *d, ExpChar = HexStartCharacter + ('E' - 'A'); |
||
| 699 | sint n, ExpVal, nzeroes; |
||
| 700 | Boolean WithE, OK; |
||
| 701 | |||
| 702 | /* 1. mit Maximallaenge wandeln, fuehrendes Vorzeichen weg */ |
||
| 703 | |||
| 704 | (void)DestSize; |
||
| 705 | as_snprintf(pDest, DestSize, "%*.*llle", 12 + AS_FLOAT_DIG, AS_FLOAT_DIG, f); |
||
| 706 | for (p = pDest; (*p == ' ') || (*p == '+'); p++); |
||
| 707 | if (p != pDest) |
||
| 708 | strmov(pDest, p); |
||
| 709 | |||
| 710 | /* 2. Exponenten soweit als moeglich kuerzen, evtl. ganz streichen */ |
||
| 711 | |||
| 712 | p = strchr(pDest, ExpChar); |
||
| 713 | if (!p) |
||
| 714 | return; |
||
| 715 | switch (*(++p)) |
||
| 716 | { |
||
| 717 | case '+': |
||
| 718 | strmov(p, p + 1); |
||
| 719 | break; |
||
| 720 | case '-': |
||
| 721 | p++; |
||
| 722 | break; |
||
| 723 | } |
||
| 724 | |||
| 725 | while (*p == '0') |
||
| 726 | strmov(p, p + 1); |
||
| 727 | WithE = (*p != '\0'); |
||
| 728 | if (!WithE) |
||
| 729 | pDest[strlen(pDest) - 1] = '\0'; |
||
| 730 | |||
| 731 | /* 3. Nullen am Ende der Mantisse entfernen, Komma bleibt noch */ |
||
| 732 | |||
| 733 | p = WithE ? strchr(pDest, ExpChar) : pDest + strlen(pDest); |
||
| 734 | p--; |
||
| 735 | while (*p == '0') |
||
| 736 | { |
||
| 737 | strmov(p, p + 1); |
||
| 738 | p--; |
||
| 739 | } |
||
| 740 | |||
| 741 | /* 4. auf die gewuenschte Maximalstellenzahl begrenzen */ |
||
| 742 | |||
| 743 | p = WithE ? strchr(pDest, ExpChar) : pDest + strlen(pDest); |
||
| 744 | d = strchr(pDest, '.'); |
||
| 745 | n = p - d - 1; |
||
| 746 | |||
| 747 | /* 5. Maximallaenge ueberschritten ? */ |
||
| 748 | |||
| 749 | if (strlen(pDest) > MaxLen) |
||
| 750 | strmov(d + (n - (strlen(pDest) - MaxLen)), d + n); |
||
| 751 | |||
| 752 | /* 6. Exponentenwert berechnen */ |
||
| 753 | |||
| 754 | if (WithE) |
||
| 755 | { |
||
| 756 | p = strchr(pDest, ExpChar); |
||
| 757 | ExpVal = ConstLongInt(p + 1, &OK, 10); |
||
| 758 | } |
||
| 759 | else |
||
| 760 | { |
||
| 761 | p = pDest + strlen(pDest); |
||
| 762 | ExpVal = 0; |
||
| 763 | } |
||
| 764 | |||
| 765 | /* 7. soviel Platz, dass wir den Exponenten weglassen und evtl. Nullen |
||
| 766 | anhaengen koennen ? */ |
||
| 767 | |||
| 768 | if (ExpVal > 0) |
||
| 769 | { |
||
| 770 | nzeroes = ExpVal - (p - strchr(pDest, '.') - 1); /* = Zahl von Nullen, die anzuhaengen waere */ |
||
| 771 | |||
| 772 | /* 7a. nur Kommaverschiebung erforderlich. Exponenten loeschen und |
||
| 773 | evtl. auch Komma */ |
||
| 774 | |||
| 775 | if (nzeroes <= 0) |
||
| 776 | { |
||
| 777 | *p = '\0'; |
||
| 778 | d = strchr(pDest, '.'); |
||
| 779 | strmov(d, d + 1); |
||
| 780 | if (nzeroes != 0) |
||
| 781 | { |
||
| 782 | memmove(pDest + strlen(pDest) + nzeroes + 1, pDest + strlen(pDest) + nzeroes, -nzeroes); |
||
| 783 | pDest[strlen(pDest) - 1 + nzeroes] = '.'; |
||
| 784 | } |
||
| 785 | } |
||
| 786 | |||
| 787 | /* 7b. Es muessen Nullen angehaengt werden. Schauen, ob nach Loeschen von |
||
| 788 | Punkt und E-Teil genuegend Platz ist */ |
||
| 789 | |||
| 790 | else |
||
| 791 | { |
||
| 792 | n = strlen(p) + 1 + (MaxLen - strlen(pDest)); /* = Anzahl freizubekommender Zeichen+Gutschrift */ |
||
| 793 | if (n >= nzeroes) |
||
| 794 | { |
||
| 795 | *p = '\0'; |
||
| 796 | d = strchr(pDest, '.'); |
||
| 797 | strmov(d, d + 1); |
||
| 798 | d = pDest + strlen(pDest); |
||
| 799 | for (n = 0; n < nzeroes; n++) |
||
| 800 | *(d++) = '0'; |
||
| 801 | *d = '\0'; |
||
| 802 | } |
||
| 803 | } |
||
| 804 | } |
||
| 805 | |||
| 806 | /* 8. soviel Platz, dass Exponent wegkann und die Zahl mit vielen Nullen |
||
| 807 | vorne geschrieben werden kann ? */ |
||
| 808 | |||
| 809 | else if (ExpVal < 0) |
||
| 810 | { |
||
| 811 | n = (-ExpVal) - (strlen(p)); /* = Verlaengerung nach Operation */ |
||
| 812 | if (strlen(pDest) + n <= MaxLen) |
||
| 813 | { |
||
| 814 | *p = '\0'; |
||
| 815 | d = strchr(pDest, '.'); |
||
| 816 | strmov(d, d + 1); |
||
| 817 | d = (pDest[0] == '-') ? pDest + 1 : pDest; |
||
| 818 | memmove(d - ExpVal + 1, d, strlen(pDest) + 1); |
||
| 819 | *(d++) = '0'; |
||
| 820 | *(d++) = '.'; |
||
| 821 | for (n = 0; n < -ExpVal - 1; n++) |
||
| 822 | *(d++) = '0'; |
||
| 823 | } |
||
| 824 | } |
||
| 825 | |||
| 826 | |||
| 827 | /* 9. Ueberfluessiges Komma entfernen */ |
||
| 828 | |||
| 829 | if (WithE) |
||
| 830 | p = strchr(pDest, ExpChar); |
||
| 831 | else |
||
| 832 | p = pDest + strlen(pDest); |
||
| 833 | if (p && (*(p - 1) == '.')) |
||
| 834 | strmov(p - 1, p); |
||
| 835 | } |
||
| 836 | |||
| 837 | /****************************************************************************/ |
||
| 838 | /* Symbol in String wandeln */ |
||
| 839 | |||
| 840 | void StrSym(const TempResult *t, Boolean WithSystem, as_dynstr_t *p_dest, unsigned Radix) |
||
| 841 | { |
||
| 842 | LargeInt IntVal; |
||
| 843 | |||
| 844 | if (p_dest->capacity) |
||
| 845 | p_dest->p_str[0] = '\0'; |
||
| 846 | switch (t->Typ) |
||
| 847 | { |
||
| 848 | case TempInt: |
||
| 849 | IntVal = t->Contents.Int; |
||
| 850 | IsInt: |
||
| 851 | { |
||
| 852 | String Buf; |
||
| 853 | |||
| 854 | if (WithSystem) |
||
| 855 | { |
||
| 856 | switch (IntConstMode) |
||
| 857 | { |
||
| 858 | case eIntConstModeMoto: |
||
| 859 | as_sdprcatf(p_dest, "%s", GetIntConstMotoPrefix(Radix)); |
||
| 860 | break; |
||
| 861 | case eIntConstModeC: |
||
| 862 | as_sdprcatf(p_dest, "%s", GetIntConstCPrefix(Radix)); |
||
| 863 | break; |
||
| 864 | case eIntConstModeIBM: |
||
| 865 | as_sdprcatf(p_dest, "%s", GetIntConstIBMPrefix(Radix)); |
||
| 866 | break; |
||
| 867 | default: |
||
| 868 | break; |
||
| 869 | } |
||
| 870 | } |
||
| 871 | SysString(Buf, sizeof(Buf), IntVal, Radix, |
||
| 872 | 1, (16 == Radix) && (IntConstMode == eIntConstModeIntel), |
||
| 873 | HexStartCharacter, SplitByteCharacter); |
||
| 874 | as_sdprcatf(p_dest, "%s", Buf); |
||
| 875 | if (WithSystem) |
||
| 876 | { |
||
| 877 | switch (IntConstMode) |
||
| 878 | { |
||
| 879 | case eIntConstModeIntel: |
||
| 880 | as_sdprcatf(p_dest, GetIntConstIntelSuffix(Radix)); |
||
| 881 | break; |
||
| 882 | case eIntConstModeIBM: |
||
| 883 | as_sdprcatf(p_dest, GetIntConstIBMSuffix(Radix)); |
||
| 884 | break; |
||
| 885 | default: |
||
| 886 | break; |
||
| 887 | } |
||
| 888 | } |
||
| 889 | break; |
||
| 890 | } |
||
| 891 | case TempFloat: |
||
| 892 | FloatString(p_dest->p_str, p_dest->capacity, t->Contents.Float); |
||
| 893 | break; |
||
| 894 | case TempString: |
||
| 895 | as_tempres_append_dynstr(p_dest, t, 10); |
||
| 896 | break; |
||
| 897 | case TempReg: |
||
| 898 | if (t->Contents.RegDescr.Dissect) |
||
| 899 | t->Contents.RegDescr.Dissect(p_dest->p_str, p_dest->capacity, t->Contents.RegDescr.Reg, t->DataSize); |
||
| 900 | else |
||
| 901 | { |
||
| 902 | IntVal = t->Contents.RegDescr.Reg; |
||
| 903 | goto IsInt; |
||
| 904 | } |
||
| 905 | break; |
||
| 906 | default: |
||
| 907 | as_sdprintf(p_dest, "???"); |
||
| 908 | } |
||
| 909 | } |
||
| 910 | |||
| 911 | /****************************************************************************/ |
||
| 912 | /* Listingzaehler zuruecksetzen */ |
||
| 913 | |||
| 914 | void ResetPageCounter(void) |
||
| 915 | { |
||
| 916 | int z; |
||
| 917 | |||
| 918 | for (z = 0; z <= ChapMax; z++) |
||
| 919 | PageCounter[z] = 0; |
||
| 920 | LstCounter = 0; |
||
| 921 | ChapDepth = 0; |
||
| 922 | } |
||
| 923 | |||
| 924 | /*--------------------------------------------------------------------------*/ |
||
| 925 | /* eine neue Seite im Listing beginnen */ |
||
| 926 | |||
| 927 | void NewPage(ShortInt Level, Boolean WithFF) |
||
| 928 | { |
||
| 929 | ShortInt z; |
||
| 930 | String Header, s; |
||
| 931 | char Save; |
||
| 932 | |||
| 933 | if (ListOn == 0) |
||
| 934 | return; |
||
| 935 | |||
| 936 | LstCounter = 0; |
||
| 937 | |||
| 938 | if (ChapDepth < (Byte) Level) |
||
| 939 | { |
||
| 940 | memmove(PageCounter + (Level - ChapDepth), PageCounter, (ChapDepth + 1) * sizeof(Word)); |
||
| 941 | for (z = 0; z <= Level - ChapDepth; PageCounter[z++] = 1); |
||
| 942 | ChapDepth = Level; |
||
| 943 | } |
||
| 944 | for (z = 0; z <= Level - 1; PageCounter[z++] = 1); |
||
| 945 | PageCounter[Level]++; |
||
| 946 | |||
| 947 | if ((WithFF) && (!ListToNull)) |
||
| 948 | { |
||
| 949 | errno = 0; |
||
| 950 | fprintf(LstFile, "%c", Char_FF); |
||
| 951 | ChkIO(ErrNum_ListWrError); |
||
| 952 | } |
||
| 953 | |||
| 954 | as_snprintf(Header, sizeof(Header), " AS V%s%s%s", |
||
| 955 | Version, |
||
| 956 | getmessage(Num_HeadingFileNameLab), |
||
| 957 | NamePart(SourceFile)); |
||
| 958 | if (strcmp(CurrFileName, "INTERNAL") |
||
| 959 | && *CurrFileName |
||
| 960 | && strcmp(NamePart(CurrFileName), NamePart(SourceFile))) |
||
| 961 | { |
||
| 962 | strmaxcat(Header, "(", STRINGSIZE); |
||
| 963 | strmaxcat(Header, NamePart(CurrFileName), STRINGSIZE); |
||
| 964 | strmaxcat(Header, ")", STRINGSIZE); |
||
| 965 | } |
||
| 966 | strmaxcat(Header, getmessage(Num_HeadingPageLab), STRINGSIZE); |
||
| 967 | |||
| 968 | for (z = ChapDepth; z >= 0; z--) |
||
| 969 | { |
||
| 970 | as_snprintf(s, sizeof(s), IntegerFormat, PageCounter[z]); |
||
| 971 | strmaxcat(Header, s, STRINGSIZE); |
||
| 972 | if (z != 0) |
||
| 973 | strmaxcat(Header, ".", STRINGSIZE); |
||
| 974 | } |
||
| 975 | |||
| 976 | strmaxcat(Header, " - ", STRINGSIZE); |
||
| 977 | NLS_CurrDateString(s, sizeof(s)); |
||
| 978 | strmaxcat(Header, s, STRINGSIZE); |
||
| 979 | strmaxcat(Header, " ", STRINGSIZE); |
||
| 980 | NLS_CurrTimeString(False, s, sizeof(s)); |
||
| 981 | strmaxcat(Header, s, STRINGSIZE); |
||
| 982 | |||
| 983 | if (PageWidth != 0) |
||
| 984 | while (strlen(Header) > PageWidth) |
||
| 985 | { |
||
| 986 | Save = Header[PageWidth]; |
||
| 987 | Header[PageWidth] = '\0'; |
||
| 988 | if (!ListToNull) |
||
| 989 | { |
||
| 990 | errno = 0; |
||
| 991 | fprintf(LstFile, "%s\n", Header); |
||
| 992 | ChkIO(ErrNum_ListWrError); |
||
| 993 | } |
||
| 994 | Header[PageWidth] = Save; |
||
| 995 | strmov(Header, Header + PageWidth); |
||
| 996 | } |
||
| 997 | |||
| 998 | if (!ListToNull) |
||
| 999 | { |
||
| 1000 | errno = 0; |
||
| 1001 | fprintf(LstFile, "%s\n", Header); |
||
| 1002 | ChkIO(ErrNum_ListWrError); |
||
| 1003 | |||
| 1004 | if (PrtTitleString[0]) |
||
| 1005 | { |
||
| 1006 | errno = 0; |
||
| 1007 | fprintf(LstFile, "%s\n", PrtTitleString); |
||
| 1008 | ChkIO(ErrNum_ListWrError); |
||
| 1009 | } |
||
| 1010 | |||
| 1011 | errno = 0; |
||
| 1012 | fprintf(LstFile, "\n\n"); |
||
| 1013 | ChkIO(ErrNum_ListWrError); |
||
| 1014 | } |
||
| 1015 | } |
||
| 1016 | |||
| 1017 | /*--------------------------------------------------------------------------*/ |
||
| 1018 | /* eine Zeile ins Listing schieben */ |
||
| 1019 | |||
| 1020 | void WrLstLine(const char *Line) |
||
| 1021 | { |
||
| 1022 | int LLength; |
||
| 1023 | char bbuf[2500]; |
||
| 1024 | String LLine; |
||
| 1025 | int blen = 0, hlen, z, Start; |
||
| 1026 | |||
| 1027 | if ((ListOn == 0) || (ListToNull)) |
||
| 1028 | return; |
||
| 1029 | |||
| 1030 | if (PageLength == 0) |
||
| 1031 | { |
||
| 1032 | errno = 0; |
||
| 1033 | fprintf(LstFile, "%s\n", Line); |
||
| 1034 | ChkIO(ErrNum_ListWrError); |
||
| 1035 | } |
||
| 1036 | else |
||
| 1037 | { |
||
| 1038 | if ((PageWidth == 0) || ((strlen(Line) << 3) < PageWidth)) |
||
| 1039 | LLength = 1; |
||
| 1040 | else |
||
| 1041 | { |
||
| 1042 | blen = 0; |
||
| 1043 | for (z = 0; z < (int)strlen(Line); z++) |
||
| 1044 | if (Line[z] == Char_HT) |
||
| 1045 | { |
||
| 1046 | memset(bbuf + blen, ' ', 8 - (blen & 7)); |
||
| 1047 | blen += 8 - (blen&7); |
||
| 1048 | } |
||
| 1049 | else |
||
| 1050 | bbuf[blen++] = Line[z]; |
||
| 1051 | LLength = blen / PageWidth; |
||
| 1052 | if (blen % PageWidth) |
||
| 1053 | LLength++; |
||
| 1054 | } |
||
| 1055 | if (LLength == 1) |
||
| 1056 | { |
||
| 1057 | errno = 0; |
||
| 1058 | fprintf(LstFile, "%s\n", Line); |
||
| 1059 | ChkIO(ErrNum_ListWrError); |
||
| 1060 | if ((++LstCounter) == PageLength) |
||
| 1061 | NewPage(0, True); |
||
| 1062 | } |
||
| 1063 | else |
||
| 1064 | { |
||
| 1065 | Start = 0; |
||
| 1066 | for (z = 1; z <= LLength; z++) |
||
| 1067 | { |
||
| 1068 | hlen = PageWidth; |
||
| 1069 | if (blen - Start < hlen) |
||
| 1070 | hlen = blen - Start; |
||
| 1071 | memcpy(LLine, bbuf + Start, hlen); |
||
| 1072 | LLine[hlen] = '\0'; |
||
| 1073 | errno = 0; |
||
| 1074 | fprintf(LstFile, "%s\n", LLine); |
||
| 1075 | if ((++LstCounter) == PageLength) |
||
| 1076 | NewPage(0, True); |
||
| 1077 | Start += hlen; |
||
| 1078 | } |
||
| 1079 | } |
||
| 1080 | } |
||
| 1081 | } |
||
| 1082 | |||
| 1083 | /*****************************************************************************/ |
||
| 1084 | /* Ausdruck in Spalte vor Listing */ |
||
| 1085 | |||
| 1086 | void SetListLineVal(TempResult *t) |
||
| 1087 | { |
||
| 1088 | as_dynstr_t str; |
||
| 1089 | |||
| 1090 | as_dynstr_ini(&str, STRINGSIZE); |
||
| 1091 | StrSym(t, True, &str, ListRadixBase); |
||
| 1092 | as_snprintf(ListLine, STRINGSIZE, "=%s", str.p_str); |
||
| 1093 | as_dynstr_free(&str); |
||
| 1094 | } |
||
| 1095 | |||
| 1096 | /*!------------------------------------------------------------------------ |
||
| 1097 | * \fn PrintOneLineMuted(FILE *pFile, const char *pLine, |
||
| 1098 | const struct sLineComp *pMuteComponent, |
||
| 1099 | const struct sLineComp *pMuteComponent2) |
||
| 1100 | * \brief print a line, with a certain component muted out (i.e. replaced by spaces) |
||
| 1101 | * \param pFile where to write |
||
| 1102 | * \param pLine line to print |
||
| 1103 | * \param pMuteComponent component to mute in printout |
||
| 1104 | * ------------------------------------------------------------------------ */ |
||
| 1105 | |||
| 1106 | static Boolean CompMatch(int Col, const struct sLineComp *pComp) |
||
| 1107 | { |
||
| 1108 | return (pComp |
||
| 1109 | && (pComp->StartCol >= 0) |
||
| 1110 | && (Col >= pComp->StartCol) |
||
| 1111 | && (Col < pComp->StartCol + (int)pComp->Len)); |
||
| 1112 | } |
||
| 1113 | |||
| 1114 | void PrintOneLineMuted(FILE *pFile, const char *pLine, |
||
| 1115 | const struct sLineComp *pMuteComponent, |
||
| 1116 | const struct sLineComp *pMuteComponent2) |
||
| 1117 | { |
||
| 1118 | int z, Len = strlen(pLine); |
||
| 1119 | Boolean Match; |
||
| 1120 | |||
| 1121 | errno = 0; |
||
| 1122 | for (z = 0; z < Len; z++) |
||
| 1123 | { |
||
| 1124 | Match = CompMatch(z, pMuteComponent) || CompMatch(z, pMuteComponent2); |
||
| 1125 | fputc(Match ? ' ' : pLine[z], pFile); |
||
| 1126 | } |
||
| 1127 | fputc('\n', pFile); |
||
| 1128 | ChkIO(ErrNum_ListWrError); |
||
| 1129 | } |
||
| 1130 | |||
| 1131 | /*!------------------------------------------------------------------------ |
||
| 1132 | * \fn PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer, |
||
| 1133 | char Marker, const struct sLineComp *pLineComp) |
||
| 1134 | * \brief print a line, optionally with a marking of a component below |
||
| 1135 | * \param pFile where to write |
||
| 1136 | * \param pLine line to print/underline |
||
| 1137 | * \param pPrefix what to print before (under)line |
||
| 1138 | * \param pTrailer what to print after (under)line |
||
| 1139 | * \param Marker character to use for marking |
||
| 1140 | * \param pLineComp position and length of optional marker |
||
| 1141 | * ------------------------------------------------------------------------ */ |
||
| 1142 | |||
| 1143 | void PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer, |
||
| 1144 | char Marker, const struct sLineComp *pLineComp) |
||
| 1145 | { |
||
| 1146 | const char *pRun; |
||
| 1147 | int z; |
||
| 1148 | |||
| 1149 | fputs(pPrefix, pFile); |
||
| 1150 | for (pRun = pLine; *pRun; pRun++) |
||
| 1151 | fputc(TabCompressed(*pRun), pFile); |
||
| 1152 | fprintf(pFile, "%s\n", pTrailer); |
||
| 1153 | |||
| 1154 | if (pLineComp && (pLineComp->StartCol >= 0) && (pLineComp->Len > 0)) |
||
| 1155 | { |
||
| 1156 | fputs(pPrefix, pFile); |
||
| 1157 | if (pLineComp->StartCol > 0) |
||
| 1158 | fprintf(pFile, "%*s", pLineComp->StartCol, ""); |
||
| 1159 | for (z = 0; z < (int)pLineComp->Len; z++) |
||
| 1160 | fputc(Marker, pFile); |
||
| 1161 | fprintf(pFile, "%s\n", pTrailer); |
||
| 1162 | } |
||
| 1163 | } |
||
| 1164 | |||
| 1165 | /****************************************************************************/ |
||
| 1166 | /* einen Symbolnamen auf Gueltigkeit ueberpruefen */ |
||
| 1167 | |||
| 1168 | static Byte GetValidSymChar(unsigned Ch) |
||
| 1169 | { |
||
| 1170 | return (Ch < ValidSymCharLen) ? ValidSymChar[Ch] : 0; |
||
| 1171 | } |
||
| 1172 | |||
| 1173 | static char *ChkNameUpTo(const char *pSym, const char *pUpTo, Byte _Mask) |
||
| 1174 | { |
||
| 1175 | Byte Mask = _Mask; |
||
| 1176 | unsigned Ch; |
||
| 1177 | const char *pPrev; |
||
| 1178 | |||
| 1179 | if (!*pSym) |
||
| 1180 | return (char*)pSym; |
||
| 1181 | |||
| 1182 | while (*pSym && (pSym != pUpTo)) |
||
| 1183 | { |
||
| 1184 | pPrev = pSym; |
||
| 1185 | if (ValidSymCharLen > 256) |
||
| 1186 | Ch = UTF8ToUnicode(&pSym); |
||
| 1187 | else |
||
| 1188 | Ch = ((unsigned int)*pSym++) & 0xff; |
||
| 1189 | |||
| 1190 | if (!(GetValidSymChar(Ch) & Mask)) |
||
| 1191 | return (char*)pPrev; |
||
| 1192 | Mask = _Mask << 1; |
||
| 1193 | } |
||
| 1194 | return (char*)pSym; |
||
| 1195 | } |
||
| 1196 | |||
| 1197 | char *ChkSymbNameUpTo(const char *pSym, const char *pUpTo) |
||
| 1198 | { |
||
| 1199 | char *pResult = ChkNameUpTo(pSym, pUpTo, VALID_S1); |
||
| 1200 | |||
| 1201 | /* If NULL as UpTo was given, and all is fine up to end of string, |
||
| 1202 | also return NULL as result. So Equation 'Result==UpTo' is fulfilled: */ |
||
| 1203 | |||
| 1204 | if (!pUpTo && !*pResult) |
||
| 1205 | pResult= NULL; |
||
| 1206 | return pResult; |
||
| 1207 | } |
||
| 1208 | |||
| 1209 | Boolean ChkSymbName(const char *pSym) |
||
| 1210 | { |
||
| 1211 | const char *pEnd = ChkSymbNameUpTo(pSym, NULL); |
||
| 1212 | return *pSym && !pEnd; |
||
| 1213 | } |
||
| 1214 | |||
| 1215 | char *ChkMacSymbNameUpTo(const char *pSym, const char *pUpTo) |
||
| 1216 | { |
||
| 1217 | char *pResult = ChkNameUpTo(pSym, pUpTo, VALID_M1); |
||
| 1218 | |||
| 1219 | /* If NULL as UpTo was given, and all is fine up to end of string, |
||
| 1220 | also return NULL as result. So Equation 'Result==UpTo' is fulfilled: */ |
||
| 1221 | |||
| 1222 | if (!pUpTo && !*pResult) |
||
| 1223 | pResult= NULL; |
||
| 1224 | return pResult; |
||
| 1225 | } |
||
| 1226 | |||
| 1227 | Boolean ChkMacSymbName(const char *pSym) |
||
| 1228 | { |
||
| 1229 | const char *pEnd = ChkMacSymbNameUpTo(pSym, NULL); |
||
| 1230 | return *pSym && !pEnd; |
||
| 1231 | } |
||
| 1232 | |||
| 1233 | Boolean ChkMacSymbChar(char ch) |
||
| 1234 | { |
||
| 1235 | return !!(GetValidSymChar(ch) & (VALID_M1 | VALID_MN)); |
||
| 1236 | } |
||
| 1237 | |||
| 1238 | /*!------------------------------------------------------------------------ |
||
| 1239 | * \fn visible_strlen(const char *pSym) |
||
| 1240 | * \brief retrieve 'visible' length of string, regarding multi-byte |
||
| 1241 | sequences for UTF-8 |
||
| 1242 | * \param pSym symbol name |
||
| 1243 | * \return visible length in characters |
||
| 1244 | * ------------------------------------------------------------------------ */ |
||
| 1245 | |||
| 1246 | unsigned visible_strlen(const char *pSym) |
||
| 1247 | { |
||
| 1248 | if (ValidSymCharLen > 256) |
||
| 1249 | { |
||
| 1250 | unsigned Result = 0; |
||
| 1251 | |||
| 1252 | while (*pSym) |
||
| 1253 | Result += as_wcwidth(UTF8ToUnicode(&pSym)); |
||
| 1254 | return Result; |
||
| 1255 | } |
||
| 1256 | else |
||
| 1257 | return strlen(pSym); |
||
| 1258 | } |
||
| 1259 | |||
| 1260 | /****************************************************************************/ |
||
| 1261 | |||
| 1262 | LargeWord ProgCounter(void) |
||
| 1263 | { |
||
| 1264 | return PCs[ActPC]; |
||
| 1265 | } |
||
| 1266 | |||
| 1267 | /*--------------------------------------------------------------------------*/ |
||
| 1268 | /* aktuellen Programmzaehler mit Phasenverschiebung holen */ |
||
| 1269 | |||
| 1270 | LargeWord EProgCounter(void) |
||
| 1271 | { |
||
| 1272 | return PCs[ActPC] + Phases[ActPC]; |
||
| 1273 | } |
||
| 1274 | |||
| 1275 | /*--------------------------------------------------------------------------*/ |
||
| 1276 | /* Granularitaet des aktuellen Segments holen */ |
||
| 1277 | |||
| 1278 | Word Granularity(void) |
||
| 1279 | { |
||
| 1280 | return Grans[ActPC]; |
||
| 1281 | } |
||
| 1282 | |||
| 1283 | /*--------------------------------------------------------------------------*/ |
||
| 1284 | /* Linstingbreite des aktuellen Segments holen */ |
||
| 1285 | |||
| 1286 | Word ListGran(void) |
||
| 1287 | { |
||
| 1288 | return ListGrans[ActPC]; |
||
| 1289 | } |
||
| 1290 | |||
| 1291 | /*--------------------------------------------------------------------------*/ |
||
| 1292 | /* pruefen, ob alle Symbole einer Formel im korrekten Adressraum lagen */ |
||
| 1293 | |||
| 1294 | void ChkSpace(Byte AddrSpace, unsigned AddrSpaceMask) |
||
| 1295 | { |
||
| 1296 | AddrSpaceMask &= ~(1 << AddrSpace); |
||
| 1297 | |||
| 1298 | if (AddrSpaceMask) WrError(ErrNum_WrongSegment); |
||
| 1299 | } |
||
| 1300 | |||
| 1301 | /****************************************************************************/ |
||
| 1302 | /* eine Chunkliste im Listing ausgeben & Speicher loeschen */ |
||
| 1303 | |||
| 1304 | void PrintChunk(ChunkList *NChunk, DissectBitProc Dissect, int ItemsPerLine) |
||
| 1305 | { |
||
| 1306 | LargeWord NewMin, FMin; |
||
| 1307 | Boolean Found; |
||
| 1308 | Word p = 0, z; |
||
| 1309 | int BufferZ; |
||
| 1310 | String BufferS; |
||
| 1311 | int MaxItemLen = 79 / ItemsPerLine; |
||
| 1312 | |||
| 1313 | NewMin = 0; |
||
| 1314 | BufferZ = 0; |
||
| 1315 | *BufferS = '\0'; |
||
| 1316 | |||
| 1317 | do |
||
| 1318 | { |
||
| 1319 | /* niedrigsten Start finden, der ueberhalb des letzten Endes liegt */ |
||
| 1320 | |||
| 1321 | Found = False; |
||
| 1322 | FMin = IntTypeDefs[LargeUIntType].Max; |
||
| 1323 | for (z = 0; z < NChunk->RealLen; z++) |
||
| 1324 | if (NChunk->Chunks[z].Start >= NewMin) |
||
| 1325 | if (FMin > NChunk->Chunks[z].Start) |
||
| 1326 | { |
||
| 1327 | Found = True; |
||
| 1328 | FMin = NChunk->Chunks[z].Start; |
||
| 1329 | p = z; |
||
| 1330 | } |
||
| 1331 | |||
| 1332 | if (Found) |
||
| 1333 | { |
||
| 1334 | char Num[30]; |
||
| 1335 | |||
| 1336 | Dissect(Num, sizeof(Num), NChunk->Chunks[p].Start); |
||
| 1337 | strmaxcat(BufferS, Num, STRINGSIZE); |
||
| 1338 | if (NChunk->Chunks[p].Length != 1) |
||
| 1339 | { |
||
| 1340 | strmaxcat(BufferS, "-", STRINGSIZE); |
||
| 1341 | Dissect(Num, sizeof(Num), NChunk->Chunks[p].Start + NChunk->Chunks[p].Length - 1); |
||
| 1342 | strmaxcat(BufferS, Num, STRINGSIZE); |
||
| 1343 | } |
||
| 1344 | strmaxcat(BufferS, Blanks(MaxItemLen - strlen(BufferS) % MaxItemLen), STRINGSIZE); |
||
| 1345 | if (++BufferZ == ItemsPerLine) |
||
| 1346 | { |
||
| 1347 | WrLstLine(BufferS); |
||
| 1348 | *BufferS = '\0'; |
||
| 1349 | BufferZ = 0; |
||
| 1350 | } |
||
| 1351 | NewMin = NChunk->Chunks[p].Start + NChunk->Chunks[p].Length; |
||
| 1352 | } |
||
| 1353 | } |
||
| 1354 | while (Found); |
||
| 1355 | |||
| 1356 | if (BufferZ != 0) |
||
| 1357 | WrLstLine(BufferS); |
||
| 1358 | } |
||
| 1359 | |||
| 1360 | /*--------------------------------------------------------------------------*/ |
||
| 1361 | /* Listen ausgeben */ |
||
| 1362 | |||
| 1363 | void PrintUseList(void) |
||
| 1364 | { |
||
| 1365 | int z, z2, l; |
||
| 1366 | String s; |
||
| 1367 | |||
| 1368 | for (z = 1; z < SegCount; z++) |
||
| 1369 | if (SegChunks[z].Chunks) |
||
| 1370 | { |
||
| 1371 | as_snprintf(s, sizeof(s), " %s%s%s", |
||
| 1372 | getmessage(Num_ListSegListHead1), SegNames[z], |
||
| 1373 | getmessage(Num_ListSegListHead2)); |
||
| 1374 | WrLstLine(s); |
||
| 1375 | strcpy(s, " "); |
||
| 1376 | l = strlen(SegNames[z]) + strlen(getmessage(Num_ListSegListHead1)) + strlen(getmessage(Num_ListSegListHead2)); |
||
| 1377 | for (z2 = 0; z2 < l; z2++) |
||
| 1378 | strmaxcat(s, "-", STRINGSIZE); |
||
| 1379 | WrLstLine(s); |
||
| 1380 | WrLstLine(""); |
||
| 1381 | PrintChunk(SegChunks + z, |
||
| 1382 | (z == SegBData) ? DissectBit : Default_DissectBit, |
||
| 1383 | (z == SegBData) ? 3 : 4); |
||
| 1384 | WrLstLine(""); |
||
| 1385 | } |
||
| 1386 | } |
||
| 1387 | |||
| 1388 | void ClearUseList(void) |
||
| 1389 | { |
||
| 1390 | int z; |
||
| 1391 | |||
| 1392 | for (z = 1; z < SegCount; z++) |
||
| 1393 | ClearChunk(SegChunks + z); |
||
| 1394 | } |
||
| 1395 | |||
| 1396 | /****************************************************************************/ |
||
| 1397 | /* Include-Pfadlistenverarbeitung */ |
||
| 1398 | |||
| 1399 | /*!------------------------------------------------------------------------ |
||
| 1400 | * \fn get_first_path_from_list(const char *p_path_list, char *p_first_path, size_t first_path_size) |
||
| 1401 | * \brief extract first path from list of paths |
||
| 1402 | * \param p_path_list path list |
||
| 1403 | * \param p_first_path where to put component |
||
| 1404 | * \param first_path_size buffer size |
||
| 1405 | * \return p_path_list for next call of get_first_path_from_list() |
||
| 1406 | * ------------------------------------------------------------------------ */ |
||
| 1407 | |||
| 1408 | static const char *get_first_path_from_list(const char *p_path_list, char *p_first_path, size_t first_path_size) |
||
| 1409 | { |
||
| 1410 | const char *p; |
||
| 1411 | |||
| 1412 | p = strchr(p_path_list, DIRSEP); |
||
| 1413 | if (!p) |
||
| 1414 | { |
||
| 1415 | strmaxcpy(p_first_path, p_path_list, first_path_size); |
||
| 1416 | return ""; |
||
| 1417 | } |
||
| 1418 | else |
||
| 1419 | { |
||
| 1420 | strmemcpy(p_first_path, first_path_size, p_path_list, p - p_path_list); |
||
| 1421 | return p + 1; |
||
| 1422 | } |
||
| 1423 | } |
||
| 1424 | |||
| 1425 | /*!------------------------------------------------------------------------ |
||
| 1426 | * \fn AddIncludeList(const char *p_new_path) |
||
| 1427 | * \brief add path to include list |
||
| 1428 | * \param p_new_path path to add |
||
| 1429 | * ------------------------------------------------------------------------ */ |
||
| 1430 | |||
| 1431 | void AddIncludeList(const char *p_new_path) |
||
| 1432 | { |
||
| 1433 | const char *p_list_run = IncludeList; |
||
| 1434 | String one_path; |
||
| 1435 | |||
| 1436 | /* path already present in list? */ |
||
| 1437 | |||
| 1438 | while (*p_list_run) |
||
| 1439 | { |
||
| 1440 | p_list_run = get_first_path_from_list(p_list_run, one_path, sizeof(one_path)); |
||
| 1441 | if (!strcmp(one_path, p_new_path)) |
||
| 1442 | return; |
||
| 1443 | } |
||
| 1444 | |||
| 1445 | /* no -> prepend */ |
||
| 1446 | |||
| 1447 | if (*IncludeList != '\0') |
||
| 1448 | strmaxprep(IncludeList, SDIRSEP, STRINGSIZE); |
||
| 1449 | strmaxprep(IncludeList, p_new_path, STRINGSIZE); |
||
| 1450 | } |
||
| 1451 | |||
| 1452 | /*!------------------------------------------------------------------------ |
||
| 1453 | * \fn RemoveIncludeList(const char *p_rem_path) |
||
| 1454 | * \brief remove one path from include list |
||
| 1455 | * \param p_rem_path path to remove |
||
| 1456 | * ------------------------------------------------------------------------ */ |
||
| 1457 | |||
| 1458 | void RemoveIncludeList(const char *p_rem_path) |
||
| 1459 | { |
||
| 1460 | String one_path; |
||
| 1461 | const char *p_list_run, *p_list_next; |
||
| 1462 | |||
| 1463 | p_list_run = IncludeList; |
||
| 1464 | while (*p_list_run) |
||
| 1465 | { |
||
| 1466 | p_list_next = get_first_path_from_list(p_list_run, one_path, sizeof(one_path)); |
||
| 1467 | if (!strcmp(one_path, p_rem_path)) |
||
| 1468 | strmov((char*)p_list_run, p_list_next); |
||
| 1469 | else |
||
| 1470 | p_list_run = p_list_next; |
||
| 1471 | } |
||
| 1472 | } |
||
| 1473 | |||
| 1474 | /****************************************************************************/ |
||
| 1475 | /* Listen mit Ausgabedateien */ |
||
| 1476 | |||
| 1477 | void ClearOutList(void) |
||
| 1478 | { |
||
| 1479 | ClearStringList(&OutList); |
||
| 1480 | } |
||
| 1481 | |||
| 1482 | void AddToOutList(const char *NewName) |
||
| 1483 | { |
||
| 1484 | AddStringListLast(&OutList, NewName); |
||
| 1485 | } |
||
| 1486 | |||
| 1487 | void RemoveFromOutList(const char *OldName) |
||
| 1488 | { |
||
| 1489 | RemoveStringList(&OutList, OldName); |
||
| 1490 | } |
||
| 1491 | |||
| 1492 | char *MoveFromOutListFirst(void) |
||
| 1493 | { |
||
| 1494 | return MoveAndCutStringListFirst(&OutList); |
||
| 1495 | } |
||
| 1496 | |||
| 1497 | void ClearShareOutList(void) |
||
| 1498 | { |
||
| 1499 | ClearStringList(&ShareOutList); |
||
| 1500 | } |
||
| 1501 | |||
| 1502 | void AddToShareOutList(const char *NewName) |
||
| 1503 | { |
||
| 1504 | AddStringListLast(&ShareOutList, NewName); |
||
| 1505 | } |
||
| 1506 | |||
| 1507 | void RemoveFromShareOutList(const char *OldName) |
||
| 1508 | { |
||
| 1509 | RemoveStringList(&ShareOutList, OldName); |
||
| 1510 | } |
||
| 1511 | |||
| 1512 | char *MoveFromShareOutListFirst(void) |
||
| 1513 | { |
||
| 1514 | return MoveAndCutStringListFirst(&ShareOutList); |
||
| 1515 | } |
||
| 1516 | |||
| 1517 | void ClearListOutList(void) |
||
| 1518 | { |
||
| 1519 | ClearStringList(&ListOutList); |
||
| 1520 | } |
||
| 1521 | |||
| 1522 | void AddToListOutList(const char *NewName) |
||
| 1523 | { |
||
| 1524 | AddStringListLast(&ListOutList, NewName); |
||
| 1525 | } |
||
| 1526 | |||
| 1527 | void RemoveFromListOutList(const char *OldName) |
||
| 1528 | { |
||
| 1529 | RemoveStringList(&ListOutList, OldName); |
||
| 1530 | } |
||
| 1531 | |||
| 1532 | char *MoveFromListOutListFirst(void) |
||
| 1533 | { |
||
| 1534 | return MoveAndCutStringListFirst(&ListOutList); |
||
| 1535 | } |
||
| 1536 | |||
| 1537 | /****************************************************************************/ |
||
| 1538 | /* Tokenverarbeitung */ |
||
| 1539 | |||
| 1540 | typedef int (*tCompareFnc)(const char *s1, const char *s2, size_t n); |
||
| 1541 | |||
| 1542 | int ReplaceLine(as_dynstr_t *p_str, const char *pSearch, const char *pReplace, Boolean CaseSensitive) |
||
| 1543 | { |
||
| 1544 | int SearchLen = strlen(pSearch), ReplaceLen = strlen(pReplace), StrLen = strlen(p_str->p_str), DeltaLen = ReplaceLen - SearchLen; |
||
| 1545 | int NumReplace = 0, Pos, End, CmpRes, Avail, nCopy, nMove; |
||
| 1546 | tCompareFnc Compare = CaseSensitive ? strncmp : as_strncasecmp; |
||
| 1547 | |||
| 1548 | Pos = 0; |
||
| 1549 | while (Pos <= StrLen - SearchLen) |
||
| 1550 | { |
||
| 1551 | End = Pos + SearchLen; |
||
| 1552 | CmpRes = Compare(&p_str->p_str[Pos], pSearch, SearchLen); |
||
| 1553 | if ((!CmpRes) |
||
| 1554 | && ((Pos == 0) || !ChkMacSymbChar(p_str->p_str[Pos - 1])) |
||
| 1555 | && ((End >= StrLen) || !ChkMacSymbChar(p_str->p_str[End]))) |
||
| 1556 | { |
||
| 1557 | if (StrLen + DeltaLen + 1 > (int)p_str->capacity) |
||
| 1558 | as_dynstr_realloc(p_str, as_dynstr_roundup_len(p_str->capacity + DeltaLen)); |
||
| 1559 | Avail = p_str->capacity - 1 - Pos; |
||
| 1560 | nCopy = ReplaceLen; if (nCopy > Avail) nCopy = Avail; |
||
| 1561 | Avail -= nCopy; |
||
| 1562 | nMove = StrLen - (Pos + SearchLen); if (nMove > Avail) nMove = Avail; |
||
| 1563 | memmove(&p_str->p_str[Pos + nCopy], &p_str->p_str[Pos + SearchLen], nMove); |
||
| 1564 | memcpy(&p_str->p_str[Pos], pReplace, nCopy); |
||
| 1565 | p_str->p_str[Pos + nCopy + nMove] = '\0'; |
||
| 1566 | Pos += nCopy; |
||
| 1567 | StrLen += DeltaLen; |
||
| 1568 | NumReplace++; |
||
| 1569 | } |
||
| 1570 | else |
||
| 1571 | Pos++; |
||
| 1572 | } |
||
| 1573 | return NumReplace; |
||
| 1574 | } |
||
| 1575 | |||
| 1576 | static void SetToken(char *Token, unsigned TokenNum) |
||
| 1577 | { |
||
| 1578 | Token[0] = (TokenNum >> 4) + 1; |
||
| 1579 | Token[1] = (TokenNum & 15) + 1; |
||
| 1580 | Token[2] = 0; |
||
| 1581 | } |
||
| 1582 | |||
| 1583 | /*!------------------------------------------------------------------------ |
||
| 1584 | * \fn CompressLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str, Boolean ThisCaseSensitive) |
||
| 1585 | * \brief compress tokens in line |
||
| 1586 | * \param TokNam name to compress into token |
||
| 1587 | * \param TokenNum token # |
||
| 1588 | * \param p_str string to work on |
||
| 1589 | * \param ThisCaseSensitive operate case sensitive? |
||
| 1590 | * ------------------------------------------------------------------------ */ |
||
| 1591 | |||
| 1592 | int CompressLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str, Boolean ThisCaseSensitive) |
||
| 1593 | { |
||
| 1594 | char Token[3]; |
||
| 1595 | SetToken(Token, TokenNum); |
||
| 1596 | return ReplaceLine(p_str, TokNam, Token, ThisCaseSensitive); |
||
| 1597 | } |
||
| 1598 | |||
| 1599 | /*!------------------------------------------------------------------------ |
||
| 1600 | * \fn ExpandLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str) |
||
| 1601 | * \brief expand tokens in line |
||
| 1602 | * \param TokNam name to expand token to |
||
| 1603 | * \param TokenNum token # |
||
| 1604 | * \param p_str string to work on |
||
| 1605 | * ------------------------------------------------------------------------ */ |
||
| 1606 | |||
| 1607 | void ExpandLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str) |
||
| 1608 | { |
||
| 1609 | char Token[3]; |
||
| 1610 | SetToken(Token, TokenNum); |
||
| 1611 | (void)ReplaceLine(p_str, Token, TokNam, True); |
||
| 1612 | } |
||
| 1613 | |||
| 1614 | void KillCtrl(char *Line) |
||
| 1615 | { |
||
| 1616 | char *z; |
||
| 1617 | |||
| 1618 | if (*(z = Line) == '\0') |
||
| 1619 | return; |
||
| 1620 | do |
||
| 1621 | { |
||
| 1622 | if (*z == '\0'); |
||
| 1623 | else if (*z == Char_HT) |
||
| 1624 | { |
||
| 1625 | strmov(z, z + 1); |
||
| 1626 | strprep(z, Blanks(8 - ((z - Line) % 8))); |
||
| 1627 | } |
||
| 1628 | else if ((*z & 0xe0) == 0) |
||
| 1629 | *z = ' '; |
||
| 1630 | z++; |
||
| 1631 | } |
||
| 1632 | while (*z != '\0'); |
||
| 1633 | } |
||
| 1634 | |||
| 1635 | /****************************************************************************/ |
||
| 1636 | /* Buchhaltung */ |
||
| 1637 | |||
| 1638 | void BookKeeping(void) |
||
| 1639 | { |
||
| 1640 | if (MakeUseList) |
||
| 1641 | if (AddChunk(SegChunks + ActPC, ProgCounter(), CodeLen, ActPC == SegCode)) |
||
| 1642 | WrError(ErrNum_Overlap); |
||
| 1643 | if (DebugMode != DebugNone) |
||
| 1644 | { |
||
| 1645 | AddSectionUsage(ProgCounter(), CodeLen); |
||
| 1646 | AddLineInfo(InMacroFlag, CurrLine, CurrFileName, ActPC, PCs[ActPC], CodeLen); |
||
| 1647 | } |
||
| 1648 | } |
||
| 1649 | |||
| 1650 | /****************************************************************************/ |
||
| 1651 | /* Differenz zwischen zwei Zeiten mit Tagesueberlauf berechnen */ |
||
| 1652 | |||
| 1653 | long DTime(long t1, long t2) |
||
| 1654 | { |
||
| 1655 | LongInt d; |
||
| 1656 | |||
| 1657 | d = t2 - t1; |
||
| 1658 | if (d < 0) d += (24*360000); |
||
| 1659 | return (d > 0) ? d : -d; |
||
| 1660 | } |
||
| 1661 | |||
| 1662 | /*--------------------------------------------------------------------------*/ |
||
| 1663 | /* Init/Deinit passes */ |
||
| 1664 | |||
| 1665 | typedef struct sProcStore |
||
| 1666 | { |
||
| 1667 | struct sProcStore *pNext; |
||
| 1668 | SimpProc Proc; |
||
| 1669 | } tProcStore; |
||
| 1670 | |||
| 1671 | static tProcStore *pInitPassProcStore = NULL, |
||
| 1672 | *pClearUpProcStore = NULL; |
||
| 1673 | |||
| 1674 | void InitPass(void) |
||
| 1675 | { |
||
| 1676 | tProcStore *pStore; |
||
| 1677 | |||
| 1678 | for (pStore = pInitPassProcStore; pStore; pStore = pStore->pNext) |
||
| 1679 | pStore->Proc(); |
||
| 1680 | } |
||
| 1681 | |||
| 1682 | void ClearUp(void) |
||
| 1683 | { |
||
| 1684 | tProcStore *pStore; |
||
| 1685 | |||
| 1686 | for (pStore = pClearUpProcStore; pStore; pStore = pStore->pNext) |
||
| 1687 | pStore->Proc(); |
||
| 1688 | } |
||
| 1689 | |||
| 1690 | void AddInitPassProc(SimpProc NewProc) |
||
| 1691 | { |
||
| 1692 | tProcStore *pNewStore = (tProcStore*)calloc(1, sizeof(*pNewStore)); |
||
| 1693 | |||
| 1694 | pNewStore->pNext = pInitPassProcStore; |
||
| 1695 | pNewStore->Proc = NewProc; |
||
| 1696 | pInitPassProcStore = pNewStore; |
||
| 1697 | } |
||
| 1698 | |||
| 1699 | void AddClearUpProc(SimpProc NewProc) |
||
| 1700 | { |
||
| 1701 | tProcStore *pNewStore = (tProcStore*)calloc(1, sizeof(*pNewStore)); |
||
| 1702 | |||
| 1703 | pNewStore->pNext = pClearUpProcStore; |
||
| 1704 | pNewStore->Proc = NewProc; |
||
| 1705 | pClearUpProcStore = pNewStore; |
||
| 1706 | } |
||
| 1707 | |||
| 1708 | /*!------------------------------------------------------------------------ |
||
| 1709 | * \fn GTime(void) |
||
| 1710 | * \brief fetch time of day in units of 10 ms |
||
| 1711 | * \return time of day |
||
| 1712 | * ------------------------------------------------------------------------ */ |
||
| 1713 | |||
| 1714 | #ifdef __MSDOS__ |
||
| 1715 | |||
| 1716 | #include <dos.h> |
||
| 1717 | |||
| 1718 | long GTime(void) |
||
| 1719 | { |
||
| 1720 | struct time tbuf; |
||
| 1721 | long result; |
||
| 1722 | |||
| 1723 | gettime(&tbuf); |
||
| 1724 | result = tbuf.ti_hour; |
||
| 1725 | result = (result * 60) + tbuf.ti_min; |
||
| 1726 | result = (result * 60) + tbuf.ti_sec; |
||
| 1727 | result = (result * 100) + tbuf.ti_hund; |
||
| 1728 | return result; |
||
| 1729 | } |
||
| 1730 | |||
| 1731 | # define GTIME_DEFINED |
||
| 1732 | #endif /* __MSDOS__ */ |
||
| 1733 | |||
| 1734 | #ifdef __IBMC__ |
||
| 1735 | |||
| 1736 | #include <time.h> |
||
| 1737 | #define INCL_DOSDATETIME |
||
| 1738 | #include <os2.h> |
||
| 1739 | |||
| 1740 | long GTime(void) |
||
| 1741 | { |
||
| 1742 | DATETIME dt; |
||
| 1743 | struct tm ts; |
||
| 1744 | DosGetDateTime(&dt); |
||
| 1745 | memset(&ts, 0, sizeof(ts)); |
||
| 1746 | ts.tm_year = dt.year - 1900; |
||
| 1747 | ts.tm_mon = dt.month - 1; |
||
| 1748 | ts.tm_mday = dt.day; |
||
| 1749 | ts.tm_hour = dt.hours; |
||
| 1750 | ts.tm_min = dt.minutes; |
||
| 1751 | ts.tm_sec = dt.seconds; |
||
| 1752 | return (mktime(&ts) * 100) + (dt.hundredths); |
||
| 1753 | } |
||
| 1754 | |||
| 1755 | # define GTIME_DEFINED |
||
| 1756 | #endif /* __IBMC__ */ |
||
| 1757 | |||
| 1758 | #ifdef _WIN32 |
||
| 1759 | |||
| 1760 | # include <windows.h> |
||
| 1761 | |||
| 1762 | # if !AS_HAS_LONGLONG |
||
| 1763 | # include "math64.h" |
||
| 1764 | # endif |
||
| 1765 | |||
| 1766 | long GTime(void) |
||
| 1767 | { |
||
| 1768 | FILETIME ft; |
||
| 1769 | |||
| 1770 | GetSystemTimeAsFileTime(&ft); |
||
| 1771 | # if !AS_HAS_LONGLONG |
||
| 1772 | { |
||
| 1773 | static const t64 offs = { 0xd53e8000, 0x019db1de }, |
||
| 1774 | div = { 100000, 0 }, |
||
| 1775 | mod = { 8640000, 0 }; |
||
| 1776 | t64 acc; |
||
| 1777 | |||
| 1778 | /* time since 1 Jan 1601 in 100ns units */ |
||
| 1779 | acc.low = ft.dwLowDateTime; |
||
| 1780 | acc.high = ft.dwHighDateTime; |
||
| 1781 | /* -> time since 1 Jan 1970 in 100ns units */ |
||
| 1782 | sub64(&acc, &acc, &offs); |
||
| 1783 | /* -> time since 1 Jan 1970 in 10ms units */ |
||
| 1784 | div64(&acc, &acc, &div); |
||
| 1785 | /* -> time since 0:00:00.0 in 10ms units */ |
||
| 1786 | mod64(&acc, &acc, &mod); |
||
| 1787 | return acc.low; |
||
| 1788 | } |
||
| 1789 | # else /* AS_HAS_LONGLONG */ |
||
| 1790 | # define _W32_FT_OFFSET (116444736000000000ULL) |
||
| 1791 | unsigned long long time_tot; |
||
| 1792 | /* time since 1 Jan 1601 in 100ns units */ |
||
| 1793 | time_tot = ((unsigned long long)ft.dwLowDateTime ) ; |
||
| 1794 | time_tot += ((unsigned long long)ft.dwHighDateTime) << 32; |
||
| 1795 | |||
| 1796 | /* -> time since 1 Jan 1970 in 100ns units */ |
||
| 1797 | time_tot -= _W32_FT_OFFSET; |
||
| 1798 | /* -> time since 1 Jan 1970 in 10ms units */ |
||
| 1799 | time_tot /= 100000ULL; |
||
| 1800 | /* -> time since 0:00:00.0 in 10ms units */ |
||
| 1801 | time_tot %= 8640000ULL; |
||
| 1802 | return time_tot; |
||
| 1803 | # endif /* !AS_HAS_LONGLONG */ |
||
| 1804 | } |
||
| 1805 | |||
| 1806 | # define GTIME_DEFINED |
||
| 1807 | #endif /* _WIN32 */ |
||
| 1808 | |||
| 1809 | #ifndef GTIME_DEFINED |
||
| 1810 | |||
| 1811 | #include <sys/time.h> |
||
| 1812 | |||
| 1813 | #ifdef NEED_GETTIMEOFDAY |
||
| 1814 | # include <portability.h> |
||
| 1815 | #endif |
||
| 1816 | |||
| 1817 | long GTime(void) |
||
| 1818 | { |
||
| 1819 | struct timeval tv; |
||
| 1820 | |||
| 1821 | gettimeofday(&tv, NULL); |
||
| 1822 | tv.tv_sec %= 86400; |
||
| 1823 | return (tv.tv_sec * 100) + (tv.tv_usec/10000); |
||
| 1824 | } |
||
| 1825 | |||
| 1826 | #endif /* GTIME_DEFINED */ |
||
| 1827 | |||
| 1828 | /*-------------------------------------------------------------------------*/ |
||
| 1829 | /* Stackfehler abfangen - bis auf DOS nur Dummies */ |
||
| 1830 | |||
| 1831 | #ifdef __TURBOC__ |
||
| 1832 | |||
| 1833 | #ifdef __DPMI16__ |
||
| 1834 | #else |
||
| 1835 | unsigned _stklen = STKSIZE; |
||
| 1836 | unsigned _ovrbuffer = 64*48; |
||
| 1837 | #endif |
||
| 1838 | #include <malloc.h> |
||
| 1839 | |||
| 1840 | void ChkStack(void) |
||
| 1841 | { |
||
| 1842 | LongWord avail = stackavail(); |
||
| 1843 | if (avail < MinStack) |
||
| 1844 | WrError(ErrNum_StackOvfl); |
||
| 1845 | if (avail < LowStack) |
||
| 1846 | LowStack = avail; |
||
| 1847 | } |
||
| 1848 | |||
| 1849 | void ResetStack(void) |
||
| 1850 | { |
||
| 1851 | LowStack = stackavail(); |
||
| 1852 | } |
||
| 1853 | |||
| 1854 | LongWord StackRes(void) |
||
| 1855 | { |
||
| 1856 | return LowStack - MinStack; |
||
| 1857 | } |
||
| 1858 | #endif /* __TURBOC__ */ |
||
| 1859 | |||
| 1860 | #ifdef CKMALLOC |
||
| 1861 | #undef malloc |
||
| 1862 | #undef realloc |
||
| 1863 | |||
| 1864 | void *ckmalloc(size_t s) |
||
| 1865 | { |
||
| 1866 | void *tmp; |
||
| 1867 | |||
| 1868 | #ifdef __TURBOC__ |
||
| 1869 | if (coreleft() < HEAPRESERVE + s) |
||
| 1870 | WrError(ErrNum_HeapOvfl); |
||
| 1871 | #endif |
||
| 1872 | |||
| 1873 | tmp = malloc(s); |
||
| 1874 | if (!tmp && (s > 0)) |
||
| 1875 | WrError(ErrNum_HeapOvfl); |
||
| 1876 | return tmp; |
||
| 1877 | } |
||
| 1878 | |||
| 1879 | void *ckrealloc(void *p, size_t s) |
||
| 1880 | { |
||
| 1881 | void *tmp; |
||
| 1882 | |||
| 1883 | #ifdef __TURBOC__ |
||
| 1884 | if (coreleft() < HEAPRESERVE + s) |
||
| 1885 | WrError(ErrNum_HeapOvfl); |
||
| 1886 | #endif |
||
| 1887 | |||
| 1888 | tmp = realloc(p, s); |
||
| 1889 | if (!tmp) |
||
| 1890 | WrError(ErrNum_HeapOvfl); |
||
| 1891 | return tmp; |
||
| 1892 | } |
||
| 1893 | #endif |
||
| 1894 | |||
| 1895 | static void SetValidSymChar(unsigned Ch, Byte Value) |
||
| 1896 | { |
||
| 1897 | ValidSymChar[Ch] = Value; |
||
| 1898 | } |
||
| 1899 | |||
| 1900 | static void SetValidSymChars(unsigned Start, unsigned Stop, Byte Value) |
||
| 1901 | { |
||
| 1902 | for (; Start <= Stop; Start++) |
||
| 1903 | SetValidSymChar(Start, Value); |
||
| 1904 | } |
||
| 1905 | |||
| 1906 | static as_cmd_result_t cmd_underscore_macroargs(Boolean negate, const char *p_arg) |
||
| 1907 | { |
||
| 1908 | unsigned ch = (unsigned)'_'; |
||
| 1909 | |||
| 1910 | UNUSED(p_arg); |
||
| 1911 | if (negate) |
||
| 1912 | ValidSymChar[ch] &= ~(VALID_M1 | VALID_MN); |
||
| 1913 | else |
||
| 1914 | ValidSymChar[ch] |= (VALID_M1 | VALID_MN); |
||
| 1915 | return e_cmd_ok; |
||
| 1916 | } |
||
| 1917 | |||
| 1918 | static const as_cmd_rec_t cmd_params[] = |
||
| 1919 | { |
||
| 1920 | { "underscore-macroargs", cmd_underscore_macroargs } |
||
| 1921 | }; |
||
| 1922 | |||
| 1923 | void asmsub_init(void) |
||
| 1924 | { |
||
| 1925 | #ifdef __TURBOC__ |
||
| 1926 | #ifdef __MSDOS__ |
||
| 1927 | #ifdef __DPMI16__ |
||
| 1928 | char *MemFlag, *p; |
||
| 1929 | String MemVal, TempName; |
||
| 1930 | unsigned long FileLen; |
||
| 1931 | #else |
||
| 1932 | char *envval; |
||
| 1933 | int ovrerg; |
||
| 1934 | #endif |
||
| 1935 | #endif |
||
| 1936 | #endif |
||
| 1937 | |||
| 1938 | InitStringList(&CopyrightList); |
||
| 1939 | InitStringList(&OutList); |
||
| 1940 | InitStringList(&ShareOutList); |
||
| 1941 | InitStringList(&ListOutList); |
||
| 1942 | |||
| 1943 | #ifdef __TURBOC__ |
||
| 1944 | #ifdef __MSDOS__ |
||
| 1945 | #ifdef __DPMI16__ |
||
| 1946 | /* Fuer DPMI evtl. Swapfile anlegen */ |
||
| 1947 | |||
| 1948 | MemFlag = getenv("ASXSWAP"); |
||
| 1949 | if (MemFlag) |
||
| 1950 | { |
||
| 1951 | strmaxcpy(MemVal, MemFlag, STRINGSIZE); |
||
| 1952 | p = strchr(MemVal, ','); |
||
| 1953 | if (!p) |
||
| 1954 | strcpy(TempName, "ASX.TMP"); |
||
| 1955 | else |
||
| 1956 | { |
||
| 1957 | *p = NULL; |
||
| 1958 | strcpy(TempName, MemVal); |
||
| 1959 | strmov(MemVal, p + 1); |
||
| 1960 | }; |
||
| 1961 | KillBlanks(TempName); |
||
| 1962 | KillBlanks(MemVal); |
||
| 1963 | FileLen = strtol(MemFlag, &p, 0); |
||
| 1964 | if (*p != '\0') |
||
| 1965 | { |
||
| 1966 | fputs(getmessage(Num_ErrMsgInvSwapSize), stderr); |
||
| 1967 | exit(4); |
||
| 1968 | } |
||
| 1969 | if (MEMinitSwapFile(TempName, FileLen << 20) != RTM_OK) |
||
| 1970 | { |
||
| 1971 | fputs(getmessage(Num_ErrMsgSwapTooBig), stderr); |
||
| 1972 | exit(4); |
||
| 1973 | } |
||
| 1974 | } |
||
| 1975 | #else |
||
| 1976 | /* Bei DOS Auslagerung Overlays in XMS/EMS versuchen */ |
||
| 1977 | |||
| 1978 | envval = getenv("USEXMS"); |
||
| 1979 | if ((envval) && (as_toupper(*envval) == 'N')) |
||
| 1980 | ovrerg = -1; |
||
| 1981 | else |
||
| 1982 | ovrerg = _OvrInitExt(0, 0); |
||
| 1983 | if (ovrerg != 0) |
||
| 1984 | { |
||
| 1985 | envval = getenv("USEEMS"); |
||
| 1986 | if ((!envval) || (as_toupper(*envval) != 'N')) |
||
| 1987 | _OvrInitEms(0, 0, 0); |
||
| 1988 | } |
||
| 1989 | #endif |
||
| 1990 | #endif |
||
| 1991 | #endif |
||
| 1992 | |||
| 1993 | #ifdef __TURBOC__ |
||
| 1994 | StartStack = stackavail(); |
||
| 1995 | LowStack = stackavail(); |
||
| 1996 | MinStack = StartStack - STKSIZE + 0x800; |
||
| 1997 | #else |
||
| 1998 | StartStack = LowStack = MinStack = 0; |
||
| 1999 | #endif |
||
| 2000 | |||
| 2001 | as_cmd_register(cmd_params, as_array_size(cmd_params)); |
||
| 2002 | |||
| 2003 | /* initialize array of valid characters */ |
||
| 2004 | |||
| 2005 | ValidSymCharLen = (NLS_GetCodepage() == eCodepageUTF8) ? 1280 : 256; |
||
| 2006 | ValidSymChar = (Byte*) calloc(ValidSymCharLen, sizeof(Byte)); |
||
| 2007 | |||
| 2008 | /* The basic ASCII stuff: letters, dot and underscore are allowed |
||
| 2009 | anywhere, numbers not at beginning: */ |
||
| 2010 | |||
| 2011 | SetValidSymChars('a', 'z', VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2012 | SetValidSymChars('A', 'Z', VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2013 | SetValidSymChars('0', '9', VALID_SN | VALID_MN); |
||
| 2014 | SetValidSymChar ('.' , VALID_S1 | VALID_SN ); |
||
| 2015 | SetValidSymChar ('_' , VALID_S1 | VALID_SN ); |
||
| 2016 | |||
| 2017 | /* Extensions, depending on character set: */ |
||
| 2018 | |||
| 2019 | switch (NLS_GetCodepage()) |
||
| 2020 | { |
||
| 2021 | case eCodepage1251: |
||
| 2022 | SetValidSymChar (0xa3 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2023 | SetValidSymChar (0xb3 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2024 | SetValidSymChar (0xa8 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2025 | SetValidSymChar (0xb8 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2026 | SetValidSymChar (0xaa , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2027 | SetValidSymChar (0xba , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2028 | SetValidSymChar (0xaf , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2029 | SetValidSymChar (0xbf , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2030 | SetValidSymChar (0xbd , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2031 | SetValidSymChar (0xbe , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2032 | goto iso8859_1; |
||
| 2033 | case eCodepage1252: |
||
| 2034 | SetValidSymChar (0x8a , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2035 | SetValidSymChar (0x9a , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2036 | SetValidSymChar (0x8c , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2037 | SetValidSymChar (0x9c , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2038 | SetValidSymChar (0x8e , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2039 | SetValidSymChar (0x9e , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2040 | SetValidSymChar (0x9f , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2041 | goto iso8859_1; |
||
| 2042 | case eCodepage850: |
||
| 2043 | SetValidSymChars(0xb5, 0xb7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2044 | SetValidSymChars(0xc6, 0xc7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2045 | SetValidSymChars(0xd0, 0xd9, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2046 | SetValidSymChar (0xde , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2047 | SetValidSymChars(0xe0, 0xed, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2048 | /* fall-through */ |
||
| 2049 | case eCodepage437: |
||
| 2050 | SetValidSymChars(128, 165, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2051 | SetValidSymChar (225 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2052 | break; |
||
| 2053 | case eCodepage866: |
||
| 2054 | SetValidSymChars(0x80, 0xaf, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2055 | SetValidSymChars(0xe0, 0xf7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2056 | break; |
||
| 2057 | case eCodepageISO8859_15: |
||
| 2058 | SetValidSymChar (0xa6 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2059 | SetValidSymChar (0xa8 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2060 | SetValidSymChar (0xb4 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2061 | SetValidSymChar (0xb8 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2062 | SetValidSymChar (0xbc , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2063 | SetValidSymChar (0xbd , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2064 | SetValidSymChar (0xbe , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2065 | /* fall-through */ |
||
| 2066 | case eCodepageISO8859_1: |
||
| 2067 | iso8859_1: |
||
| 2068 | SetValidSymChar (0xa1 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2069 | SetValidSymChar (0xa2 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2070 | SetValidSymChars(0xc0, 0xff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2071 | break; |
||
| 2072 | case eCodepageKOI8_R: |
||
| 2073 | SetValidSymChar (0xa3 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2074 | SetValidSymChar (0xb3 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2075 | SetValidSymChars(0xc0, 0xff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2076 | break; |
||
| 2077 | case eCodepageUTF8: |
||
| 2078 | { |
||
| 2079 | const tNLSCharacterTab *pTab = GetCharacterTab(eCodepageUTF8); |
||
| 2080 | tNLSCharacter ch; |
||
| 2081 | unsigned Unicode; |
||
| 2082 | const char *pCh; |
||
| 2083 | |||
| 2084 | for (ch = (tNLSCharacter)0; ch < eCH_cnt; ch++) |
||
| 2085 | { |
||
| 2086 | if ((ch == eCH_e2) || (ch == eCH_mu) || (ch == eCH_iquest) || (ch == eCH_iexcl)) |
||
| 2087 | continue; |
||
| 2088 | pCh = &((*pTab)[ch][0]); |
||
| 2089 | Unicode = UTF8ToUnicode(&pCh); |
||
| 2090 | if (Unicode < ValidSymCharLen) |
||
| 2091 | SetValidSymChar (Unicode, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2092 | } |
||
| 2093 | |||
| 2094 | /* Greek */ |
||
| 2095 | |||
| 2096 | SetValidSymChar ( 895 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2097 | SetValidSymChar ( 902 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2098 | SetValidSymChar (1011 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2099 | SetValidSymChar (1016 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2100 | SetValidSymChar (1018 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2101 | SetValidSymChar (1019 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2102 | SetValidSymChars( 904, 974, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2103 | SetValidSymChars( 984, 1007, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2104 | |||
| 2105 | /* Cyrillic */ |
||
| 2106 | |||
| 2107 | SetValidSymChars(0x400, 0x481, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2108 | SetValidSymChars(0x48a, 0x4ff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN); |
||
| 2109 | } |
||
| 2110 | default: |
||
| 2111 | break; |
||
| 2112 | } |
||
| 2113 | |||
| 2114 | #if 0 |
||
| 2115 | for (z = 0; z < ValidSymCharLen; z++) |
||
| 2116 | { |
||
| 2117 | if (!(z & 15)) |
||
| 2118 | fprintf(stderr, "%02x:", z); |
||
| 2119 | fprintf(stderr, " %x", ValidSymChar[z]); |
||
| 2120 | if ((z & 15) == 15) |
||
| 2121 | fprintf(stderr, "\n"); |
||
| 2122 | } |
||
| 2123 | #endif |
||
| 2124 | |||
| 2125 | version_init(); |
||
| 2126 | } |