Annotation of mstools/samples/sdktools/dlgedit/rwinc.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.