|
|
1.1 ! root 1: ! 2: /******************************************************************************\ ! 3: * This is a part of the Microsoft Source Code Samples. ! 4: * Copyright (C) 1993 Microsoft Corporation. ! 5: * All rights reserved. ! 6: * This source code is only intended as a supplement to ! 7: * Microsoft Development Tools and/or WinHelp documentation. ! 8: * See these sources for detailed information regarding the ! 9: * Microsoft samples programs. ! 10: \******************************************************************************/ ! 11: ! 12: /****************************** Module Header ******************************* ! 13: * Module Name: rwinc.c ! 14: * ! 15: * Does the include file reading and writing. ! 16: * ! 17: * Functions: ! 18: * ! 19: * OpenIncludeFile() ! 20: * FreeInclude() ! 21: * WriteInc() ! 22: * LoadIncludeFile() ! 23: * GetChar() ! 24: * ReadChar() ! 25: * GetLabel() ! 26: * GetValue() ! 27: * GetWord() ! 28: * FindDefine() ! 29: * GetNextInc() ! 30: * RWToOffset() ! 31: * WriteIncChar() ! 32: * WriteIncFlush() ! 33: * WriteChangedInc() ! 34: * WriteDeletedInc() ! 35: * WriteAddedInc() ! 36: * WriteSymbol() ! 37: * WriteIDInc() ! 38: * ! 39: * Comments: ! 40: * ! 41: ****************************************************************************/ ! 42: ! 43: #include "dlgedit.h" ! 44: #include "dlgfuncs.h" ! 45: #include "dlgextrn.h" ! 46: ! 47: #include <ctype.h> ! 48: ! 49: ! 50: /* ! 51: * Field width that the symbol is printed within. This indirectly ! 52: * determines where the id value starts, because blanks are added ! 53: * after the symbol is printed up to this width value. ! 54: */ ! 55: #define CCHSYMFIELDWIDTH 27 ! 56: ! 57: /* ! 58: * Return codes from the file reading functions. ! 59: */ ! 60: #define READ_OK 1 ! 61: #define READ_EOF 2 ! 62: #define READ_BAD 3 ! 63: #define READ_WRONG 4 ! 64: #define BAD_POINTER ((VOID *)0xFFFF) ! 65: ! 66: /* ! 67: * Return codes from the GetNextInc function. ! 68: */ ! 69: #define GNI_DONE 0 ! 70: #define GNI_NOCHANGE 1 ! 71: #define GNI_CHANGED 2 ! 72: #define GNI_DELETED 3 ! 73: #define GNI_ADDED 4 ! 74: ! 75: static BYTE abBuffer[CCHFILEBUFFER]; /* Buffer for read file data. */ ! 76: static TCHAR achBuffer[CCHFILEBUFFER]; /* Unicode buffer for data. */ ! 77: static INT cbBuf; /* Pointer into achBuffer. */ ! 78: static DWORD cchFile; /* Count of characters read. */ ! 79: static DWORD cchFileMax; /* Max characters in file. */ ! 80: static DWORD fposLastDefine; /* Saves location of "#define". */ ! 81: static DWORD fposWordStart; /* Saves start of id value. */ ! 82: static BOOL fAtNewLine; /* At start or \r or \n. */ ! 83: static HANDLE hfInclude; /* The current include file. */ ! 84: ! 85: STATICFN BOOL LoadIncludeFile(VOID); ! 86: STATICFN LPTSTR GetChar(VOID); ! 87: STATICFN LPTSTR ReadChar(VOID); ! 88: STATICFN INT GetLabel(BOOL *pfDups); ! 89: STATICFN INT GetValue(PINT pnValue); ! 90: STATICFN INT GetWord(LPTSTR pch); ! 91: STATICFN INT FindDefine(VOID); ! 92: STATICFN INT GetNextInc(NPLABEL *pplReturn, BOOL fFirst); ! 93: STATICFN BOOL RWToOffset(HANDLE hfWrite, DWORD lOffset); ! 94: STATICFN BOOL WriteIncChar(HANDLE hfWrite, TCHAR ch); ! 95: STATICFN BOOL WriteIncFlush(HANDLE hfWrite); ! 96: STATICFN BOOL WriteChangedInc(HANDLE hfWrite, NPLABEL plInc); ! 97: STATICFN BOOL WriteDeletedInc(HANDLE hfWrite, NPLABEL plInc); ! 98: STATICFN BOOL WriteAddedInc(HANDLE hfWrite, NPLABEL plInc); ! 99: STATICFN BOOL WriteSymbol(HANDLE hfWrite, LPTSTR pszSymbol); ! 100: STATICFN BOOL WriteIDInc(HANDLE hfWrite, INT id); ! 101: ! 102: ! 103: ! 104: /**************************************************************************** ! 105: * OpenIncludeFile ! 106: * ! 107: * This function attempts to open and load the include file with name ! 108: * pointed to by pszOpenInclude. If pszOpenInclude is just a file name, and ! 109: * not a path, then the path is taken from szFullLoadFile. Otherwise ! 110: * pszOpenInclude itself is used. The full pathname is put in ! 111: * szFullIncludeFile and pszIncludeFile is set to point to just the file ! 112: * name in it. ! 113: * ! 114: * If fDoOpen is TRUE, the file is opened. If it is FALSE, it is assumed ! 115: * that hfInc contains the file handle to the opened include file and this ! 116: * handle is used. In addition, the caller is responsible for closing ! 117: * any passed in file handle if an error occurs. ! 118: * ! 119: * Any existing includes are freed, szFullIncludeFile is set to the full ! 120: * include path, pszIncludeFile is set to the filename portion of this full ! 121: * path and hfInclude will contain the file handle to the include file. ! 122: * ! 123: * Arguments: ! 124: * LPTSTR pszOpenInclude - name of the include file to open. ! 125: * ! 126: * Returns: ! 127: * If the load is successful, TRUE is returned. Otherwise, ! 128: * FALSE is returned. ! 129: * ! 130: ****************************************************************************/ ! 131: ! 132: BOOL OpenIncludeFile( ! 133: LPTSTR pszOpenInclude) ! 134: { ! 135: TCHAR szFullIncludeFileTemp[CCHMAXPATH]; ! 136: HCURSOR hcurSave; ! 137: BOOL fSuccess = FALSE; ! 138: ! 139: hcurSave = SetCursor(hcurWait); ! 140: ! 141: if (FileInPath(pszOpenInclude) == pszOpenInclude) { ! 142: lstrcpy(szFullIncludeFileTemp, szFullResFile); ! 143: lstrcpy(FileInPath(szFullIncludeFileTemp), pszOpenInclude); ! 144: } ! 145: else { ! 146: lstrcpy(szFullIncludeFileTemp, pszOpenInclude); ! 147: } ! 148: ! 149: /* ! 150: * Close any existing include file and free memory. ! 151: */ ! 152: FreeInclude(); ! 153: ! 154: if ((hfInclude = CreateFile(szFullIncludeFileTemp, GENERIC_READ, ! 155: FILE_SHARE_READ, NULL, OPEN_EXISTING, ! 156: FILE_FLAG_SEQUENTIAL_SCAN, NULL)) != (HANDLE)-1) { ! 157: if (LoadIncludeFile()) { ! 158: lstrcpy(szFullIncludeFile, szFullIncludeFileTemp); ! 159: pszIncludeFile = FileInPath(szFullIncludeFile); ! 160: fSuccess = TRUE; ! 161: } ! 162: ! 163: CloseHandle(hfInclude); ! 164: } ! 165: ! 166: /* ! 167: * Update the status windows symbol combo box. Update other fields ! 168: * also, in case the currently selected control's symbol was affected ! 169: * by the reading of the new include file. ! 170: */ ! 171: StatusFillSymbolList(plInclude); ! 172: StatusUpdate(); ! 173: ! 174: ShowFileStatus(TRUE); ! 175: SetCursor(hcurSave); ! 176: ! 177: return fSuccess; ! 178: } ! 179: ! 180: ! 181: ! 182: /************************************************************************ ! 183: * LoadIncludeFile ! 184: * ! 185: * This function creates or adds to plInclude with all the #define ! 186: * statements in the file with handle hfInclude. ! 187: * ! 188: * Returns: ! 189: * TRUE - Load succeeded. ! 190: * FALSE - Load failed (a read error). ! 191: * ! 192: ************************************************************************/ ! 193: ! 194: STATICFN BOOL LoadIncludeFile(VOID) ! 195: { ! 196: INT RetCode; ! 197: BOOL fDups = FALSE; ! 198: ! 199: /* ! 200: * Set char count, get file cb. ! 201: */ ! 202: cchFile = 0L; ! 203: cchFileMax = GetFileSize((HANDLE)hfInclude, NULL); ! 204: cbBuf = CCHFILEBUFFER; ! 205: fAtNewLine = TRUE; ! 206: ! 207: /* ! 208: * Loop through and extract all id definitions. ! 209: */ ! 210: while ((RetCode = FindDefine()) != READ_EOF) { ! 211: if (RetCode == READ_BAD || (RetCode = GetLabel(&fDups)) == READ_BAD) { ! 212: Message(MSG_INTERNAL); ! 213: return FALSE; ! 214: } ! 215: } ! 216: ! 217: /* ! 218: * Warn the user if there were duplicate symbols, ! 219: * or symbols with duplicate ids. ! 220: */ ! 221: if (fDups) ! 222: Message(MSG_IDUPIDS); ! 223: ! 224: return TRUE; ! 225: } ! 226: ! 227: ! 228: ! 229: /**************************************************************************** ! 230: * FindDefine ! 231: * ! 232: * This function looks for ^#define[\s\t], that "#define" at the start ! 233: * of a line and followed by a space or a tab. ! 234: * ! 235: * Returns: ! 236: * READ_OK -> All OK & #define found. ! 237: * READ_EOF -> All OK, but EOF found before #define. ! 238: * READ_BAD = Failure on read. ! 239: * ! 240: ****************************************************************************/ ! 241: ! 242: STATICFN INT FindDefine(VOID) ! 243: { ! 244: LPTSTR pchIn; ! 245: LPTSTR pchCmp; ! 246: BOOL fLastAtNewLine; ! 247: ! 248: tryagain: ! 249: ! 250: /* ! 251: * Skip blank lines looking for a newline followed by a '#'. ! 252: */ ! 253: while (TRUE) { ! 254: fLastAtNewLine = fAtNewLine; ! 255: pchIn = GetChar(); ! 256: ! 257: if (pchIn == NULL) ! 258: return READ_EOF; ! 259: else if (pchIn == BAD_POINTER) ! 260: return READ_BAD; ! 261: else if (fLastAtNewLine && *pchIn == CHAR_POUND) ! 262: break; ! 263: } ! 264: ! 265: /* ! 266: * At this point a newline followed by a '#' has been found. ! 267: * Begin checking for "define". Save away the file offset, ! 268: * in case we have really found one. ! 269: */ ! 270: fposLastDefine = cchFile - 1; ! 271: pchCmp = ids(IDS_DEFINE); ! 272: do { ! 273: pchIn = GetChar(); ! 274: ! 275: if (pchIn == BAD_POINTER) ! 276: return READ_BAD; ! 277: else if (pchIn == NULL || *pchIn != *pchCmp++) ! 278: goto tryagain; ! 279: } while (*pchCmp); ! 280: ! 281: /* ! 282: * Finally, look for the trailing space or tab after the "#define". ! 283: */ ! 284: pchIn = GetChar(); ! 285: if (pchIn == BAD_POINTER) ! 286: return READ_BAD; ! 287: else if (pchIn == NULL || (*pchIn != CHAR_SPACE && *pchIn != CHAR_TAB)) ! 288: goto tryagain; ! 289: ! 290: return READ_OK; ! 291: } ! 292: ! 293: ! 294: ! 295: /************************************************************************ ! 296: * GetLabel ! 297: * ! 298: * This function gets the next two words from the file hfInclude and treats ! 299: * them as a label and id, respectively. It allocates another LABEL ! 300: * and string to hold this information. ! 301: * ! 302: * Arguments: ! 303: * BOOL *pfDups = Points to a BOOL that will be set to TRUE if AddLabel ! 304: * finds a duplicate symbol or id. ! 305: * ! 306: * Returns: ! 307: * READ_OK -> All OK. ! 308: * READ_BAD = Failure on read. ! 309: * ! 310: ************************************************************************/ ! 311: ! 312: STATICFN INT GetLabel( ! 313: BOOL *pfDups) ! 314: { ! 315: INT id; ! 316: INT RetCode; ! 317: TCHAR szLabel[CCHTEXTMAX]; ! 318: ! 319: /* ! 320: * Get string and ID at current position ! 321: */ ! 322: switch (RetCode = GetWord(szLabel)) { ! 323: case READ_OK: ! 324: if ((RetCode = GetValue(&id)) == READ_OK) { ! 325: AddLabel(szLabel, id, fposLastDefine, ! 326: (INT)(fposWordStart - fposLastDefine), ! 327: &plInclude, &plDelInclude, NULL, pfDups); ! 328: } ! 329: ! 330: break; ! 331: ! 332: default: ! 333: break; ! 334: } ! 335: ! 336: return RetCode; ! 337: } ! 338: ! 339: ! 340: ! 341: /************************************************************************ ! 342: * GetWord ! 343: * ! 344: * This function uses GetChar to get the next word from the include ! 345: * file. First it removes tabs and spaces, then it collects everything ! 346: * to the next white space. Finally it null terminates the word. ! 347: * ! 348: * Arguments: ! 349: * LPTSTR pch - Where to put the word. ! 350: * ! 351: * Returns: ! 352: * READ_OK - a word was found. ! 353: * READ_EOF - EOF was found. ! 354: * READ_BAD - Error on Read. ! 355: * READ_WRONG - Found other than ' ' or '\t' followed by a letter, ! 356: * number or _, +, -. ! 357: * ! 358: ************************************************************************/ ! 359: ! 360: STATICFN INT GetWord( ! 361: LPTSTR pch) ! 362: { ! 363: TCHAR ch; ! 364: LPTSTR pchIn; ! 365: ! 366: /* ! 367: * Skip spaces. ! 368: */ ! 369: while ((pchIn = GetChar()) != NULL && pchIn != BAD_POINTER && ! 370: ((ch = *pchIn) == CHAR_SPACE || ch == CHAR_TAB)) ! 371: ; ! 372: ! 373: /* ! 374: * Errors or EOF? ! 375: */ ! 376: if (pchIn == NULL) ! 377: return READ_EOF; ! 378: else if (pchIn == BAD_POINTER) ! 379: return READ_BAD; ! 380: if (!iscsym(ch) && ch != CHAR_MINUS && ch != CHAR_PLUS) ! 381: return READ_WRONG; ! 382: ! 383: /* ! 384: * Save starting location of the word in the file. ! 385: */ ! 386: fposWordStart = cchFile - 1; ! 387: ! 388: /* ! 389: * Pick out the current word. ! 390: */ ! 391: do { ! 392: *pch++ = ch; ! 393: } while ((pchIn = GetChar()) != NULL && pchIn != BAD_POINTER && ! 394: (ch = *pchIn) != CHAR_SPACE && ch != CHAR_TAB && ! 395: ch != CHAR_NEWLINE && ch != CHAR_RETURN); ! 396: ! 397: /* ! 398: * Errors or EOF? ! 399: */ ! 400: if (pchIn == NULL) ! 401: return READ_WRONG; ! 402: else if (pchIn == BAD_POINTER) ! 403: return READ_BAD; ! 404: ! 405: /* ! 406: * Null terminate the word. ! 407: */ ! 408: *pch = (TCHAR)0; ! 409: ! 410: return READ_OK; ! 411: } ! 412: ! 413: ! 414: ! 415: /************************************************************************ ! 416: * GetChar ! 417: * ! 418: * This function returns a pointer to the next character in the ! 419: * stream hfInclude. It calls ReadChar to do the actual work. ! 420: * ! 421: * As it is reading the stream, it will compress a comment sequence to ! 422: * a single space. This means that from a slash+asterisk to the next ! 423: * asterisk+slash and from a pair of slashes to the end of the line all ! 424: * that will be returned is a single space character. ! 425: * ! 426: * Returns: ! 427: * A pointer to next character in the stream hfInclude. ! 428: * NULL => End of file. ! 429: * BAD_POINTER => Problems reading file. ! 430: * ! 431: ************************************************************************/ ! 432: ! 433: STATICFN LPTSTR GetChar(VOID) ! 434: { ! 435: register LPTSTR pch; ! 436: ! 437: /* ! 438: * Read the next character. ! 439: */ ! 440: pch = ReadChar(); ! 441: if (pch == NULL || pch == BAD_POINTER) ! 442: return pch; ! 443: ! 444: /* ! 445: * Possibly starting a comment? ! 446: */ ! 447: if (*pch == CHAR_SLASH) { ! 448: /* ! 449: * Starting a traditional comment? ! 450: */ ! 451: if (*(pch + 1) == CHAR_ASTERISK) { ! 452: /* ! 453: * Read the '*'. ! 454: */ ! 455: pch = ReadChar(); ! 456: if (pch == NULL || pch == BAD_POINTER) ! 457: return pch; ! 458: ! 459: /* ! 460: * Read until the next asterisk+slash is found. ! 461: */ ! 462: do { ! 463: pch = ReadChar(); ! 464: if (pch == NULL || pch == BAD_POINTER) ! 465: return pch; ! 466: } while (*pch != CHAR_ASTERISK || *(pch + 1) != CHAR_SLASH); ! 467: ! 468: /* ! 469: * Read the final '/'. ! 470: */ ! 471: pch = ReadChar(); ! 472: if (pch == NULL || pch == BAD_POINTER) ! 473: return pch; ! 474: ! 475: /* ! 476: * Change it to a space. ! 477: */ ! 478: *pch = CHAR_SPACE; ! 479: } ! 480: /* ! 481: * Starting a single line comment? ! 482: */ ! 483: else if (*(pch + 1) == CHAR_SLASH) { ! 484: /* ! 485: * Read up to the end of line. ! 486: */ ! 487: do { ! 488: pch = ReadChar(); ! 489: if (pch == NULL || pch == BAD_POINTER) ! 490: return pch; ! 491: } while (*(pch + 1) != CHAR_RETURN && *(pch + 1) != CHAR_NEWLINE); ! 492: ! 493: /* ! 494: * Convert the last character before the newline into a space. ! 495: */ ! 496: *pch = CHAR_SPACE; ! 497: } ! 498: } ! 499: ! 500: return pch; ! 501: } ! 502: ! 503: ! 504: ! 505: /************************************************************************ ! 506: * ReadChar ! 507: * ! 508: * This function returns a pointer to the next character in the ! 509: * stream hfInclude, but does it in a buffered fashion. That is, abBuffer ! 510: * is filled from hfInclude and pointers are returned to there. ! 511: * Note that after ReadChar is called, all previous pointers ! 512: * returned are meaningless. ! 513: * ! 514: * Returns: ! 515: * A pointer to next character in the stream hfInclude. ! 516: * NULL => End of file. ! 517: * BAD_POINTER => Problems reading file. ! 518: * ! 519: * Comments: ! 520: * May cause abBuffer to be filled from file with handle hfInclude. ! 521: * cbBuf is changed. ! 522: * cchFile is changed. ! 523: * Sets fAtNewLine = TRUE if char returned is '\n' or '\r', or FALSE ! 524: * otherwise. Not changed unless a character is returned. ! 525: * ! 526: ************************************************************************/ ! 527: ! 528: STATICFN LPTSTR ReadChar(VOID) ! 529: { ! 530: register LPTSTR pch; ! 531: INT cbRead; ! 532: ! 533: if (cchFile >= cchFileMax) ! 534: return NULL; ! 535: ! 536: if (cbBuf >= CCHFILEBUFFER) { ! 537: if ((cbRead = _lread((HFILE)hfInclude, abBuffer, CCHFILEBUFFER)) == -1) ! 538: return BAD_POINTER; ! 539: ! 540: MultiByteToWideChar(CP_ACP, 0, abBuffer, cbRead, achBuffer, ! 541: CCHFILEBUFFER); ! 542: ! 543: cbBuf = 0; ! 544: } ! 545: ! 546: pch = achBuffer + cbBuf; ! 547: cbBuf++; ! 548: cchFile++; ! 549: ! 550: if (*pch == CHAR_DOSEOF) { ! 551: cchFile = cchFileMax; ! 552: return NULL; ! 553: } ! 554: ! 555: fAtNewLine = (*pch == CHAR_RETURN || *pch == CHAR_NEWLINE) ? TRUE : FALSE; ! 556: ! 557: return pch; ! 558: } ! 559: ! 560: ! 561: ! 562: /************************************************************************ ! 563: * GetValue ! 564: * ! 565: * This function reads the next word in the file hfInclude with GetWord ! 566: * and converts that word to a number. ! 567: * ! 568: * If the second character of the word is an 'x' or 'X', the word is ! 569: * assumed to be a hex number and it is converted appropriately. ! 570: * ! 571: * Arguments: ! 572: * npsValue - Where to put the value of the next word in file. ! 573: * ! 574: * Returns: ! 575: * READ_OK - success. ! 576: * READ_BAD - am error occured. ! 577: * READ_WRONG - Something other than a number was found. ! 578: * ! 579: ************************************************************************/ ! 580: ! 581: STATICFN INT GetValue( ! 582: PINT pnValue) ! 583: { ! 584: TCHAR achValue[CCHTEXTMAX]; ! 585: LPTSTR pch; ! 586: INT RetValue; ! 587: ! 588: *pnValue = 0; ! 589: if ((RetValue = GetWord(achValue)) != READ_OK) ! 590: return RetValue; ! 591: ! 592: /* ! 593: * Verify we have only a number. ! 594: */ ! 595: pch = achValue; ! 596: if (pch[1] == CHAR_CAP_X || pch[1] == CHAR_X) { ! 597: if (*pch != CHAR_0) { ! 598: RetValue = READ_WRONG; ! 599: } ! 600: else { ! 601: for (pch += 2; *pch; pch++) { ! 602: if (!iswxdigit(*pch)) { ! 603: RetValue = READ_WRONG; ! 604: break; ! 605: } ! 606: } ! 607: ! 608: if (RetValue == READ_OK) ! 609: *pnValue = axtoi(&achValue[2]); ! 610: } ! 611: } ! 612: else { ! 613: if (!iswdigit(*pch) && *pch != CHAR_MINUS && *pch != CHAR_PLUS) { ! 614: RetValue = READ_WRONG; ! 615: } ! 616: else { ! 617: for (pch++; *pch; pch++) { ! 618: if (!iswdigit(*pch)) { ! 619: RetValue = READ_WRONG; ! 620: break; ! 621: } ! 622: } ! 623: ! 624: if (RetValue == READ_OK) ! 625: *pnValue = awtoi(achValue); ! 626: } ! 627: } ! 628: ! 629: return RetValue; ! 630: } ! 631: ! 632: ! 633: ! 634: /************************************************************************ ! 635: * FreeInclude ! 636: * ! 637: * This function frees the memory associated with an include file, ! 638: * sets global variables to match, and closes the currently open ! 639: * include file. It frees plInclude, plDelInclude and all the LABELs in them. ! 640: * It sets gfIncChged to FALSE, sets pszIncludeFile to NULL, and ! 641: * closes any open include file. ! 642: * ! 643: ************************************************************************/ ! 644: ! 645: VOID FreeInclude(VOID) ! 646: { ! 647: FreeLabels(&plInclude); ! 648: FreeLabels(&plDelInclude); ! 649: gfIncChged = FALSE; ! 650: pszIncludeFile = NULL; ! 651: } ! 652: ! 653: ! 654: ! 655: /************************************************************************ ! 656: * WriteInc ! 657: * ! 658: * This function writes the labels in plInclude to an include file. ! 659: * ! 660: * Arguments: ! 661: * HANDLE hfWrite - handle to the file to write to. ! 662: * ! 663: * Returns: ! 664: * TRUE if successful, FALSE if not. ! 665: * ! 666: ************************************************************************/ ! 667: ! 668: BOOL WriteInc( ! 669: HANDLE hfWrite) ! 670: { ! 671: INT nGNIRet; ! 672: NPLABEL plInc; ! 673: BOOL fEOF; ! 674: ! 675: /* ! 676: * Is there an include file already specified? If so, ! 677: * open it. If not, we are effectively at EOF now. ! 678: */ ! 679: if (pszIncludeFile) { ! 680: if ((hfInclude = CreateFile(szFullIncludeFile, GENERIC_READ, ! 681: FILE_SHARE_READ, NULL, OPEN_EXISTING, ! 682: FILE_FLAG_SEQUENTIAL_SCAN, NULL)) == (HANDLE)-1) { ! 683: //if the include file is missing or locked... ! 684: return FALSE; ! 685: } ! 686: ! 687: fEOF = FALSE; ! 688: } ! 689: else { ! 690: fEOF = TRUE; ! 691: } ! 692: ! 693: cchFile = 0; ! 694: cbWritePos = 0; ! 695: cbBuf = CCHFILEBUFFER; ! 696: fAtNewLine = TRUE; ! 697: ! 698: /* ! 699: * Loop through all the includes. ! 700: */ ! 701: nGNIRet = GetNextInc(&plInc, TRUE); ! 702: while (nGNIRet != GNI_DONE) { ! 703: switch (nGNIRet) { ! 704: case GNI_NOCHANGE: ! 705: break; ! 706: ! 707: case GNI_CHANGED: ! 708: if (!WriteChangedInc(hfWrite, plInc)) ! 709: return FALSE; ! 710: ! 711: break; ! 712: ! 713: case GNI_DELETED: ! 714: if (!WriteDeletedInc(hfWrite, plInc)) ! 715: return FALSE; ! 716: ! 717: break; ! 718: ! 719: case GNI_ADDED: ! 720: /* ! 721: * The first time we reach an added label, we know that ! 722: * there are no more changed or deleted ones to handle ! 723: * so we read/write up to the end of the old include file. ! 724: * This only has to be done once. ! 725: */ ! 726: if (!fEOF) { ! 727: if (!RWToOffset(hfWrite, FPOS_MAX)) ! 728: return FALSE; ! 729: ! 730: fEOF = TRUE; ! 731: ! 732: /* ! 733: * In the unlikely case that the read include file ! 734: * does not end with a carriage return and/or ! 735: * linefeed character, add them before beginning ! 736: * to write added labels. This ensures that the ! 737: * first label added always starts on a new line. ! 738: */ ! 739: if (!fAtNewLine) { ! 740: if (!WriteIncChar(hfWrite, CHAR_RETURN)) ! 741: return FALSE; ! 742: ! 743: if (!WriteIncChar(hfWrite, CHAR_NEWLINE)) ! 744: return FALSE; ! 745: } ! 746: } ! 747: ! 748: if (!WriteAddedInc(hfWrite, plInc)) ! 749: return FALSE; ! 750: ! 751: break; ! 752: } ! 753: ! 754: nGNIRet = GetNextInc(&plInc, FALSE); ! 755: } ! 756: ! 757: /* ! 758: * Write the rest of the file, if there is any left. ! 759: */ ! 760: if (!fEOF) ! 761: if (!RWToOffset(hfWrite, FPOS_MAX)) ! 762: return FALSE; ! 763: ! 764: /* ! 765: * Flush any remaining characters in the write buffer. ! 766: */ ! 767: if (!WriteIncFlush(hfWrite)) ! 768: return FALSE; ! 769: ! 770: /* ! 771: * If we just opened the old include file, close it. ! 772: */ ! 773: if (pszIncludeFile) ! 774: CloseHandle(hfInclude); ! 775: ! 776: return TRUE; ! 777: } ! 778: ! 779: ! 780: ! 781: /************************************************************************ ! 782: * GetNextInc ! 783: * ! 784: * This routine will return the next label in the plInclude and plDelInclude ! 785: * linked lists, as well as the status of the returned label. ! 786: * ! 787: * The labels will be returned in order based upon their location in the ! 788: * lists, which is their order found in the include file if their fpos ! 789: * field is not FPOS_MAX. This routine looks at the next label in both the ! 790: * plInclude and plDelInclude lists and returns the one with the lowest ! 791: * fpos. Labels are returned from plInclude and plDelInclude in order of ! 792: * their fpos until all have been returned with a valid fpos. After this, ! 793: * all new includes are returned from plInclude. ! 794: * ! 795: * Call it with fFirst equal to TRUE to initialize it. ! 796: * ! 797: * Arguments: ! 798: * NPLABEL *pplReturn - label to return. ! 799: * BOOL fFirst - TRUE if initializing. ! 800: * ! 801: * Returns: ! 802: * GNI_DONE - No more labels exist. ! 803: * GNI_NOCHANGE - An existing label is being returned. ! 804: * GNI_CHANGED - An existing label with a changed id is being returned. ! 805: * GNI_DELETED - A deleted label is being returned. ! 806: * GNI_ADDED - An added label is being returned. ! 807: * ! 808: ************************************************************************/ ! 809: ! 810: STATICFN INT GetNextInc( ! 811: NPLABEL *pplReturn, ! 812: BOOL fFirst) ! 813: { ! 814: static NPLABEL plCur; ! 815: static NPLABEL plDelCur; ! 816: ! 817: /* ! 818: * Initialize if this is the first time. ! 819: */ ! 820: if (fFirst) { ! 821: plCur = plInclude; ! 822: plDelCur = plDelInclude; ! 823: } ! 824: ! 825: /* ! 826: * Are we out of valid includes? ! 827: */ ! 828: if (!plCur) { ! 829: /* ! 830: * If there are deleted ones left, return the next one. ! 831: * Otherwise we are done. ! 832: */ ! 833: if (plDelCur) { ! 834: *pplReturn = plDelCur; ! 835: plDelCur = plDelCur->npNext; ! 836: return GNI_DELETED; ! 837: } ! 838: else { ! 839: return GNI_DONE; ! 840: } ! 841: } ! 842: /* ! 843: * Have we reached the added includes (fpos == FPOS_MAX)? ! 844: */ ! 845: else if (plCur->fpos == FPOS_MAX) { ! 846: /* ! 847: * If there are deleted ones remaining, return them first. ! 848: * Otherwise, return the next added one. ! 849: */ ! 850: if (plDelCur) { ! 851: *pplReturn = plDelCur; ! 852: plDelCur = plDelCur->npNext; ! 853: return GNI_DELETED; ! 854: } ! 855: else { ! 856: *pplReturn = plCur; ! 857: plCur = plCur->npNext; ! 858: return GNI_ADDED; ! 859: } ! 860: } ! 861: else { ! 862: /* ! 863: * Return either the next label or the next deleted label, ! 864: * based on whether there are any deleted labels and who ! 865: * has the lowest file position (fpos). ! 866: */ ! 867: if (plDelCur && plDelCur->fpos < plCur->fpos) { ! 868: *pplReturn = plDelCur; ! 869: plDelCur = plDelCur->npNext; ! 870: return GNI_DELETED; ! 871: } ! 872: else { ! 873: *pplReturn = plCur; ! 874: plCur = plCur->npNext; ! 875: /* ! 876: * Return either GNI_CHANGE or GNI_NOCHANGE based on ! 877: * whether the original id value has been changed. ! 878: */ ! 879: return ((*pplReturn)->id == (*pplReturn)->idOrig) ? ! 880: GNI_NOCHANGE : GNI_CHANGED; ! 881: } ! 882: } ! 883: } ! 884: ! 885: ! 886: ! 887: /************************************************************************ ! 888: * RWToOffset ! 889: * ! 890: * This routine reads from the current include file and writes to the ! 891: * hfWrite file up to the lOffset position in the file. If lOffset is ! 892: * set to FPOS_MAX, reads/writes are performed up to the end of the ! 893: * read file. ! 894: * ! 895: * Arguments: ! 896: * HANDLE hfWrite - handle to the file to write to. ! 897: * DWORD lOffset - where to write up to. ! 898: * ! 899: * Returns: ! 900: * TRUE if successful, FALSE if not. ! 901: * ! 902: * Comments: ! 903: * This routine relies on cchFile and cchFileMax to be properly updated ! 904: * by the reading and writing routines. ! 905: * ! 906: ************************************************************************/ ! 907: ! 908: STATICFN BOOL RWToOffset( ! 909: HANDLE hfWrite, ! 910: DWORD lOffset) ! 911: { ! 912: LPTSTR pchIn; ! 913: DWORD cbWrite; ! 914: ! 915: if (lOffset == FPOS_MAX) ! 916: lOffset = cchFileMax; ! 917: ! 918: for (cbWrite = lOffset - cchFile; cbWrite; cbWrite--) { ! 919: /* ! 920: * NULL can be returned if there is an EOF character found in ! 921: * the file. This is not an error, and we will stop reading ! 922: * and writing at this point. ! 923: */ ! 924: if ((pchIn = ReadChar()) == NULL) ! 925: return TRUE; ! 926: ! 927: /* ! 928: * If BAD_POINTER is returned, there was an error reading the ! 929: * include file. ! 930: */ ! 931: if (pchIn == BAD_POINTER) ! 932: return FALSE; ! 933: ! 934: /* ! 935: * Write out the character. ! 936: */ ! 937: if (!WriteIncChar(hfWrite, *pchIn)) ! 938: return FALSE; ! 939: } ! 940: ! 941: return TRUE; ! 942: } ! 943: ! 944: ! 945: ! 946: /************************************************************************ ! 947: * WriteIncChar ! 948: * ! 949: * This routine writes a character (ch) to the hfWrite file, doing it in a ! 950: * buffered fashion. Because it is buffered, before closing the file ! 951: * any remaining characters in the buffer must be "flushed" to disk. ! 952: * ! 953: * Arguments: ! 954: * HANDLE hfWrite - handle to the file to write to. ! 955: * TCHAR ch - character to write. ! 956: * ! 957: * Returns: ! 958: * TRUE if successful, FALSE if not. ! 959: * ! 960: * Comments: ! 961: * The globals gachWriteBuffer and cbWritePos are updated by this routine. ! 962: * ! 963: ************************************************************************/ ! 964: ! 965: STATICFN BOOL WriteIncChar( ! 966: HANDLE hfWrite, ! 967: TCHAR ch) ! 968: { ! 969: INT cbWritten; ! 970: ! 971: gachWriteBuffer[cbWritePos++] = ch; ! 972: ! 973: /* ! 974: * Is the buffer full? ! 975: */ ! 976: if (cbWritePos == CCHFILEBUFFER) { ! 977: CHAR abWriteBuffer[CCHFILEBUFFER]; ! 978: BOOL fDefCharUsed; ! 979: ! 980: WideCharToMultiByte(CP_ACP, 0, gachWriteBuffer, CCHFILEBUFFER, ! 981: abWriteBuffer, CCHFILEBUFFER, NULL, &fDefCharUsed); ! 982: ! 983: cbWritten = (INT)_lwrite((HFILE)hfWrite, abWriteBuffer, cbWritePos); ! 984: if (cbWritten != cbWritePos) ! 985: return FALSE; ! 986: ! 987: cbWritePos = 0; ! 988: } ! 989: ! 990: return TRUE; ! 991: } ! 992: ! 993: ! 994: ! 995: /************************************************************************ ! 996: * WriteIncFlush ! 997: * ! 998: * This routine flushes the write buffer. This must be done before ! 999: * the file is closed or data can be lost. ! 1000: * ! 1001: * Arguments: ! 1002: * HANDLE hfWrite - handle to the file to write to. ! 1003: * ! 1004: * Returns: ! 1005: * TRUE if successful, FALSE if not. ! 1006: * ! 1007: * Comments: ! 1008: * The global cbWritePos is updated by this routine. ! 1009: * ! 1010: ************************************************************************/ ! 1011: ! 1012: STATICFN BOOL WriteIncFlush( ! 1013: HANDLE hfWrite) ! 1014: { ! 1015: INT cbWritten; ! 1016: ! 1017: /* ! 1018: * Are any bytes remaining in the buffer? ! 1019: */ ! 1020: if (cbWritePos) { ! 1021: CHAR abWriteBuffer[CCHFILEBUFFER]; ! 1022: BOOL fDefCharUsed; ! 1023: ! 1024: WideCharToMultiByte(CP_ACP, 0, gachWriteBuffer, cbWritePos, ! 1025: abWriteBuffer, CCHFILEBUFFER, NULL, &fDefCharUsed); ! 1026: ! 1027: cbWritten = (INT)_lwrite((HFILE)hfWrite, abWriteBuffer, cbWritePos); ! 1028: if (cbWritten != cbWritePos) ! 1029: return FALSE; ! 1030: ! 1031: cbWritePos = 0; ! 1032: } ! 1033: ! 1034: return TRUE; ! 1035: } ! 1036: ! 1037: ! 1038: ! 1039: /************************************************************************ ! 1040: * WriteChangedInc ! 1041: * ! 1042: * This routine writes out a label that has had its id changed since the ! 1043: * include file was last read. ! 1044: * ! 1045: * Arguments: ! 1046: * HANDLE hfWrite - File to write to. ! 1047: * NPLABEL plInc - Label to write. ! 1048: * ! 1049: * Returns: ! 1050: * TRUE if successful, FALSE if not. ! 1051: * ! 1052: * History: ! 1053: * 03/13/90 Byron Dazey - Created. ! 1054: ************************************************************************/ ! 1055: ! 1056: STATICFN BOOL WriteChangedInc( ! 1057: HANDLE hfWrite, ! 1058: NPLABEL plInc) ! 1059: { ! 1060: TCHAR ch; ! 1061: LPTSTR pchIn; ! 1062: ! 1063: if (!RWToOffset(hfWrite, plInc->fpos + plInc->nValueOffset)) ! 1064: return FALSE; ! 1065: ! 1066: /* ! 1067: * Consume the old id value (up to the next space, tab, ! 1068: * beginning of a comment, newline or return). ! 1069: */ ! 1070: while ((pchIn = ReadChar()) != NULL && pchIn != BAD_POINTER && ! 1071: (ch = *pchIn) != CHAR_SPACE && ch != CHAR_TAB && ! 1072: ch != CHAR_SLASH && ch != CHAR_NEWLINE && ch != CHAR_RETURN) ! 1073: ; ! 1074: ! 1075: /* ! 1076: * It is an error if ReadChar returns BAD_POINTER. Note that it ! 1077: * is NOT an error if it reaches EOF (and returns NULL). ! 1078: */ ! 1079: if (pchIn == BAD_POINTER) ! 1080: return FALSE; ! 1081: ! 1082: /* ! 1083: * Write the new one. ! 1084: */ ! 1085: if (!WriteIDInc(hfWrite, plInc->id)) ! 1086: return FALSE; ! 1087: ! 1088: /* ! 1089: * Remember to write the last character read after the old value. ! 1090: */ ! 1091: if (pchIn != NULL) ! 1092: if (!WriteIncChar(hfWrite, *pchIn)) ! 1093: return FALSE; ! 1094: ! 1095: return TRUE; ! 1096: } ! 1097: ! 1098: ! 1099: ! 1100: /************************************************************************ ! 1101: * WriteDeletedInc ! 1102: * ! 1103: * This routine deletes a label in the include file, closing up the ! 1104: * space. The entire line will be deleted, unless a comment is found ! 1105: * after the id value. If so, the comment and following characters will ! 1106: * be left. ! 1107: * ! 1108: * Arguments: ! 1109: * HANDLE hfWrite - File to write to. ! 1110: * NPLABEL plInc - Label to delete. ! 1111: * ! 1112: * Returns: ! 1113: * TRUE if successful, FALSE if not. ! 1114: * ! 1115: * History: ! 1116: * 03/13/90 Byron Dazey - Created. ! 1117: ************************************************************************/ ! 1118: ! 1119: STATICFN BOOL WriteDeletedInc( ! 1120: HANDLE hfWrite, ! 1121: NPLABEL plInc) ! 1122: { ! 1123: register INT i; ! 1124: TCHAR ch; ! 1125: LPTSTR pchIn; ! 1126: ! 1127: /* ! 1128: * Read and write up to the #define to be deleted. ! 1129: */ ! 1130: if (!RWToOffset(hfWrite, plInc->fpos)) ! 1131: return FALSE; ! 1132: ! 1133: /* ! 1134: * Consume up to the id value. ! 1135: */ ! 1136: for (i = plInc->nValueOffset; i; i--) ! 1137: if ((pchIn = ReadChar()) == NULL || pchIn == BAD_POINTER) ! 1138: return FALSE; ! 1139: ! 1140: /* ! 1141: * Consume the id value and following characters up to the end of ! 1142: * the line or the beginning of a comment. ! 1143: */ ! 1144: while ((pchIn = ReadChar()) != NULL && pchIn != BAD_POINTER && ! 1145: (ch = *pchIn) != CHAR_NEWLINE && ch != CHAR_RETURN && ! 1146: ch != CHAR_SLASH) ! 1147: ; ! 1148: ! 1149: if (pchIn == BAD_POINTER) ! 1150: return FALSE; ! 1151: ! 1152: /* ! 1153: * We are done if we have reached EOF. ! 1154: */ ! 1155: if (pchIn == NULL) ! 1156: return TRUE; ! 1157: ! 1158: /* ! 1159: * If the beginning of a comment was found, be sure to write the ! 1160: * character back out and leave the rest of the comment. ! 1161: */ ! 1162: if (ch == CHAR_SLASH) { ! 1163: if (!WriteIncChar(hfWrite, ch)) ! 1164: return FALSE; ! 1165: } ! 1166: else { ! 1167: /* ! 1168: * At this point either a newline or a return was found ! 1169: * and we are going to consume it. We also want to check ! 1170: * for a return following the newline, or a newline ! 1171: * following the return and consume it also. ! 1172: */ ! 1173: if ((ch == CHAR_NEWLINE && *(pchIn + 1) == CHAR_RETURN) || ! 1174: (ch == CHAR_RETURN && *(pchIn + 1) == CHAR_NEWLINE)) ! 1175: if (ReadChar() == BAD_POINTER) ! 1176: return FALSE; ! 1177: } ! 1178: ! 1179: return TRUE; ! 1180: } ! 1181: ! 1182: ! 1183: ! 1184: /************************************************************************ ! 1185: * WriteAddedInc ! 1186: * ! 1187: * Adds a label to the new include file. ! 1188: * ! 1189: * Arguments: ! 1190: * HANDLE hfWrite - File to write to. ! 1191: * NPLABEL plInc - Label to add. ! 1192: * ! 1193: * Returns: ! 1194: * TRUE if successful, FALSE if not. ! 1195: * ! 1196: * History: ! 1197: * 03/13/90 Byron Dazey - Created. ! 1198: ************************************************************************/ ! 1199: ! 1200: STATICFN BOOL WriteAddedInc( ! 1201: HANDLE hfWrite, ! 1202: NPLABEL plInc) ! 1203: { ! 1204: register LPTSTR psz; ! 1205: ! 1206: /* ! 1207: * Write the "#define " string. ! 1208: */ ! 1209: psz = ids(IDS_POUNDDEFINE); ! 1210: while (*psz) ! 1211: if (!WriteIncChar(hfWrite, *psz++)) ! 1212: return FALSE; ! 1213: ! 1214: /* ! 1215: * Write the symbol, followed by a space. ! 1216: */ ! 1217: if (!WriteSymbol(hfWrite, plInc->pszLabel)) ! 1218: return FALSE; ! 1219: if (!WriteIncChar(hfWrite, CHAR_SPACE)) ! 1220: return FALSE; ! 1221: ! 1222: /* ! 1223: * Write the id, followed by a carriage return and newline. ! 1224: */ ! 1225: if (!WriteIDInc(hfWrite, plInc->id)) ! 1226: return FALSE; ! 1227: if (!WriteIncChar(hfWrite, CHAR_RETURN)) ! 1228: return FALSE; ! 1229: if (!WriteIncChar(hfWrite, CHAR_NEWLINE)) ! 1230: return FALSE; ! 1231: ! 1232: return TRUE; ! 1233: } ! 1234: ! 1235: ! 1236: ! 1237: /************************************************************************ ! 1238: * WriteSymbol ! 1239: * ! 1240: * Writes out a "#define DID_xxx " string to hfWrite. If the symbol ! 1241: * is smaller than CCHSYMFIELDWIDTH, it will be padded with spaces out ! 1242: * to this width. ! 1243: * ! 1244: * Arguments: ! 1245: * HANDLE hfWrite - handle to the file to write to. ! 1246: * LPTSTR pszSymbol - symbol to write. ! 1247: * ! 1248: * Returns: ! 1249: * TRUE if successful, FALSE if not. ! 1250: * ! 1251: ************************************************************************/ ! 1252: ! 1253: STATICFN BOOL WriteSymbol( ! 1254: HANDLE hfWrite, ! 1255: LPTSTR pszSymbol) ! 1256: { ! 1257: register INT cch; ! 1258: ! 1259: /* ! 1260: * Write the symbol. ! 1261: */ ! 1262: cch = 0; ! 1263: while (*pszSymbol) { ! 1264: if (!WriteIncChar(hfWrite, *pszSymbol++)) ! 1265: return FALSE; ! 1266: ! 1267: cch++; ! 1268: } ! 1269: ! 1270: /* ! 1271: * Pad the field with blanks out to CCHSYMFIELDWIDTH, if necessary. ! 1272: */ ! 1273: if (cch < CCHSYMFIELDWIDTH) { ! 1274: cch = CCHSYMFIELDWIDTH - cch; ! 1275: while (cch--) ! 1276: if (!WriteIncChar(hfWrite, CHAR_SPACE)) ! 1277: return FALSE; ! 1278: } ! 1279: ! 1280: return TRUE; ! 1281: } ! 1282: ! 1283: ! 1284: ! 1285: /************************************************************************ ! 1286: * WriteIDInc ! 1287: * ! 1288: * Writes out an id value to the hfWrite file. The format will be in ! 1289: * either hex or decimal, depending on the current mode. ! 1290: * ! 1291: * Arguments: ! 1292: * HANDLE hfWrite - File to write to. ! 1293: * INT id - ID to write. ! 1294: * ! 1295: * Returns: ! 1296: * TRUE if successful, FALSE if not. ! 1297: * ! 1298: ************************************************************************/ ! 1299: ! 1300: STATICFN BOOL WriteIDInc( ! 1301: HANDLE hfWrite, ! 1302: INT id) ! 1303: { ! 1304: register LPTSTR psz; ! 1305: TCHAR szValue[CCHIDMAX + 1]; ! 1306: ! 1307: Myitoa(id, szValue); ! 1308: ! 1309: psz = szValue; ! 1310: while (*psz) ! 1311: if (!WriteIncChar(hfWrite, *psz++)) ! 1312: return FALSE; ! 1313: ! 1314: return TRUE; ! 1315: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.