|
|
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.