9 inline operator const char *(void) const { return Text
; }
29 const char *TriggerText
;
39 // increase max number of triggers as needed,
40 // but NB current implementation cannot cope with DIFFERENT text starting with same letter.
41 // (same text with different Node is ok though)
42 TriggerNode Triggers
[200];
48 char DupeBuffer
[1000000];
52 ReplaceNode ReplaceIndex
[26][26][26][26];
56 const char *ReplaceText
;
58 const char *NextReplace
; // of just the NextText for a non-dupe, or of entire path for dupe.
63 { "Plugins","/Gsc200s/Gsc200s.rc2","/Gsc200s/res/Gsc200s.rc2",false,0 },
64 // snip other SpecialReplace entries.
67 void Replace(const char *FileID
,const char *ReplaceText
,bool DirAlreadyExists
=true,const char *ReplaceText2
=NULL
,const char *ReplaceTrigger
=NULL
,const char *ParentCreate
=NULL
)
69 ReplaceNode
*Node
=&ReplaceIndex
[FileID
[0]-'A'][FileID
[1]-'A'][FileID
[2]-'A'][FileID
[3]-'A'];
70 Node
->Text
=ReplaceText
;
71 Node
->CreatedDir
=DirAlreadyExists
;
72 Node
->CreatedParent
=ParentCreate
==NULL
;
75 Triggers
[TriggerCount
].Node
=Node
;
76 Triggers
[TriggerCount
].CopyText
=ReplaceText2
;
77 Triggers
[TriggerCount
].TriggerText
=ReplaceTrigger
?ReplaceTrigger
:ReplaceText2
;
78 Triggers
[TriggerCount
].Type
=Type_MoveOrphan
;
81 if(!DirAlreadyExists
&& strncmp(ReplaceText
,"orphaned",8)!=0)
85 if(strncmp(ParentCreate
,ReplaceText
,strlen(ParentCreate
))!=0)
86 fprintf(stderr
,"!!!!!! BAD PARAMETER !!!!!!\n");
87 // suppress parent when it gets created
88 Triggers
[TriggerCount
].Node
=NULL
;
89 Triggers
[TriggerCount
].CopyText
=NULL
;
90 Triggers
[TriggerCount
].TriggerText
=ParentCreate
;
91 Triggers
[TriggerCount
].Type
=Type_SuppressCreate
;
94 // suppress when it does get created.
95 Triggers
[TriggerCount
].Node
=NULL
;
96 Triggers
[TriggerCount
].CopyText
=NULL
;
97 Triggers
[TriggerCount
].TriggerText
=ReplaceText
;
98 Triggers
[TriggerCount
].Type
=Type_SuppressCreate
;
103 void OneShotReplace(const char *Trigger
,const char *ReplaceText
,int SkipCount
=0)
105 Triggers
[TriggerCount
].SkipCount
=SkipCount
;
106 Triggers
[TriggerCount
].CopyText
=ReplaceText
;
107 Triggers
[TriggerCount
].TriggerText
=Trigger
;
108 Triggers
[TriggerCount
].Type
=Type_OneShotReplace
;
111 void OneShotDupe(const char *Trigger
,const char *ReplaceText
,int SkipCount
=0)
113 Triggers
[TriggerCount
].SkipCount
=SkipCount
;
114 Triggers
[TriggerCount
].CopyText
=ReplaceText
;
115 Triggers
[TriggerCount
].TriggerText
=Trigger
;
116 Triggers
[TriggerCount
].Type
=Type_OneShotDupe
;
119 void MultiReplace(const char *Trigger
,const char *ReplaceText
,int SkipCount
=0)
121 Triggers
[TriggerCount
].SkipCount
=SkipCount
;
122 Triggers
[TriggerCount
].CopyText
=ReplaceText
;
123 Triggers
[TriggerCount
].TriggerText
=Trigger
;
124 Triggers
[TriggerCount
].Type
=Type_MultiReplace
;
127 void MultiDupe(const char *Trigger
,const char *ReplaceText
,int SkipCount
=0)
129 Triggers
[TriggerCount
].SkipCount
=SkipCount
;
130 Triggers
[TriggerCount
].CopyText
=ReplaceText
;
131 Triggers
[TriggerCount
].TriggerText
=Trigger
;
132 Triggers
[TriggerCount
].Type
=Type_MultiDupe
;
135 void NoMove(const char *Source
,const char *Dest
)
137 Triggers
[TriggerCount
].Node
=NULL
;
138 Triggers
[TriggerCount
].CopyText
=Source
;
139 Triggers
[TriggerCount
].TriggerText
=Dest
;
140 Triggers
[TriggerCount
].Type
=Type_NoMove
;
144 void SetupReplacements(void)
146 // first parameter to Replace MUST begin with 4 capital letters.
147 Replace("AAAAAAAA","MyProject"); //
148 Replace("CAAAAAAA","orphaned/DongleCheck",false); // /DongleCheck.cpp
149 Replace("DAAAAAAA","orphaned/DongleCheck"); // /DongleCheck.dsp
150 Replace("EAAAAAAA","orphaned/DongleCheck"); // /DongleCheck.h
151 Replace("FAAAAAAA","orphaned/DongleCheck"); // /DongleCheck.rc
152 Replace("GAAAAAAA","orphaned/DongleCheck"); // /DongleCheckDlg.cpp
153 Replace("HAAAAAAA","orphaned/DongleCheck"); // /DongleCheckDlg.h
154 Replace("IAAAAAAA","orphaned/DongleCheck"); // /ReadMe.txt
155 Replace("JAAAAAAA","orphaned/DongleCheck"); // /resource.h
156 Replace("KAAAAAAA","orphaned/DongleCheck"); // /StdAfx.cpp
157 Replace("LAAAAAAA","orphaned/DongleCheck"); // /StdAfx.h
158 Replace("EKAAAAAA","orphaned/DongleCheck/res",false); // /cross.bmp
159 Replace("FKAAAAAA","orphaned/DongleCheck/res"); // /DongleCheck.ico
160 Replace("GKAAAAAA","orphaned/DongleCheck/res"); // /DongleCheck.rc2
161 Replace("HKAAAAAA","orphaned/DongleCheck/res"); // /tick.bmp
162 // snip various other Replace(...) lines...
163 Replace("CJBAAAAA","Plugin/Gsc200s",true,"Plugins/Gsc200s","Plugins"); // /Gsc200sPlugin.cpp
164 // snip many more Replace(...) lines...
167 NoMove("Plugins/Flyte","Flyte");
169 OneShotReplace("InstallImage/Install/v2.26.ipr","InstallImage/Install/V2.26.ipr");
170 OneShotReplace("InstallImage/Install/v2.26.ipr","InstallImage/Install/V2.26.ipr");
172 // snip various fixups of stuff that failed to get put in the Plugins/Flyte project
173 // mainly OneShotReplace and OneShotDupe lines, and some Multi... lines.
179 _setmode( _fileno( stdin
), _O_BINARY
);
180 _setmode( _fileno( stdout
), _O_BINARY
);
182 memset(ReplaceIndex
,0,sizeof(ReplaceIndex
));
183 memset(RevSubst
,0,sizeof(RevSubst
));
187 const char *DirCreateText
="\n"
190 "Prop-content-length: 10\n"
191 "Content-length: 10\n"
197 int DirCreateTextLen
=strlen(DirCreateText
);
198 const char NodePathTrigger
[]="Node-path:";
199 const char NodeRevTrigger
[]="Node-copyfrom-rev: ";
200 const char NextRevTrigger
[]="Revision-number:";
202 bool LastSpace
=false;
203 const char Prefix
[]="orphaned/_";
204 const char *TriggerStart
=NULL
;
205 const char *TriggerPtr
=NULL
;
206 const char *Marker
="!!!!!!!this should not appear in the output file!!!!!!!";
209 while(fread(&c
,1,1,stdin
)) // horribly slow but simple 1 char at a time...
212 // fprintf(stderr,"Got char: %d ('%c')\n",c,c);
213 if(TriggerPtr
&& c
==*TriggerPtr
)
218 if(DupeIndex
&& TriggerStart
!=NodePathTrigger
&& TriggerStart
!=NextRevTrigger
&& TriggerStart
!=NodeRevTrigger
)
220 fprintf(stderr
,"Matched trigger in Dupe mode: %s\n",TriggerStart
);
223 // complete trigger matched.
224 if(TriggerStart
==Prefix
)
226 // matched prefix. next 8 chars are the file ID, followed by the original filename.
228 fread(&FileID
,1,8,stdin
);
231 for(ValidChars
=0;ValidChars
<8;ValidChars
++)
233 // fprintf(stderr,"FileID[%d]: %d ('%c')\n",ValidChars,FileID[ValidChars],FileID[ValidChars]);
234 if(FileID
[ValidChars
]<'A' || FileID
[ValidChars
]>'Z')
238 fprintf(stderr,"Sorry I can't cope with %s%s\n",Prefix,FileID);
240 // TODO replace the above with code to ignore the false trigger if necessary.
243 ReplaceNode
*Node
=ValidChars
<8?NULL
:&ReplaceIndex
[FileID
[0]-'A'][FileID
[1]-'A'][FileID
[2]-'A'][FileID
[3]-'A'];
244 const char *ReplaceText
=Node
?Node
->Text
:NULL
;
247 if(ReplaceText
==Marker
)
249 fwrite(&Prefix
,1,TriggerPtr
-Prefix
,stdout
);
250 fwrite(FileID
,1,8,stdout
);
254 if(!Node
->CreatedParent
)
256 // need to create the parent of ReplaceText first.
258 for(int i
=0;ReplaceText
[i
];i
++)
259 if(ReplaceText
[i
]=='/')
261 fwrite(ReplaceText
,1,LastSep
,stdout
);
262 fwrite(DirCreateText
,1,DirCreateTextLen
,stdout
);
263 Node
->CreatedParent
=true; // avoid re-creating when it is updated, copied, etc.
265 fwrite(ReplaceText
,1,strlen(ReplaceText
),stdout
);
269 // now check if this was a dir creation, and if so if we already created the same
270 // replacement dir already. If so skip ahead as next section will always be the
271 // node creation within the dir.
274 // fprintf(stderr,"Next char: %d ('%c')\n",c,c);
277 // this is referring just to the orphaned dir itself. next characters should match
278 // the following text:
279 int DirCreateMatchLen
=1;
281 while(DirCreateMatchLen
<DirCreateTextLen
)
284 if(c
!=DirCreateText
[DirCreateMatchLen
++])
286 fprintf(stderr
,"DirCreateText Mismatch at character %d (got '%c' instead of '%c'):%s\n",
287 DirCreateMatchLen
,c
,DirCreateText
[DirCreateMatchLen
-1],DirCreateText
);
288 // don't modify output, so write the stuff we read.
289 fwrite(DirCreateText
,1,DirCreateMatchLen
-1,stdout
);
290 fwrite(&c
,1,1,stdout
);
294 if(!(DirCreateMatchLen
<DirCreateTextLen
))
296 char LabelPathText
[256];
297 char LabelPathTextLen
=0;
298 char PathTriggerText
[64]="orphaned/_";
299 char PathTriggerTextLen
=strlen(strncat(PathTriggerText
,FileID
,8));
300 char PathTriggerMatchLen
=0;
301 while(PathTriggerMatchLen
<PathTriggerTextLen
)
304 if(c
==PathTriggerText
[PathTriggerMatchLen
])
305 PathTriggerMatchLen
++;
306 else if(c
=='\n' || LabelPathTextLen
+PathTriggerTextLen
>250)
308 LabelPathText
[LabelPathTextLen
]='\0';
309 fprintf(stderr
,"PathTriggerText not found after %c chars. Looking for %s in:\n%s",
310 LabelPathTextLen
+PathTriggerTextLen
,PathTriggerText
,LabelPathText
);
311 fwrite(DirCreateText
,1,DirCreateTextLen
,stdout
);
312 fwrite(LabelPathText
,1,LabelPathTextLen
,stdout
);
313 fwrite(PathTriggerText
,1,PathTriggerMatchLen
,stdout
);
314 fwrite(&c
,1,1,stdout
);
319 if(PathTriggerMatchLen
)
321 memcpy(LabelPathText
+LabelPathTextLen
,PathTriggerText
,PathTriggerMatchLen
);
322 LabelPathTextLen
+=PathTriggerMatchLen
;
323 PathTriggerMatchLen
=0;
325 LabelPathText
[LabelPathTextLen
++]=c
;
329 if(!(DirCreateMatchLen
<DirCreateTextLen
))
331 // full text matched... so do we output or not?
332 LabelPathText
[LabelPathTextLen
]='\0';
333 if(!Node
->CreatedDir
)
335 // write out DirCreateText, but replacing the last section with ReplaceText...
336 fwrite(DirCreateText
,1,DirCreateTextLen
,stdout
);
337 fwrite(LabelPathText
,1,LabelPathTextLen
,stdout
);
338 fwrite(ReplaceText
,1,strlen(ReplaceText
),stdout
);
339 // Node->CreatedDir=true;
340 // fprintf(stderr,"DirCreateText Matched and output! Label:'%s'\n",LabelPathText);
343 // fprintf(stderr,"DirCreateText Matched and suppressed label:'%s'\n",LabelPathText);
353 for(Index
=0;Index
<sizeof(SpecialReplace
)/sizeof(*SpecialReplace
) && Count
;Index
++)
355 if(strcmp(SpecialReplace
[Index
].ReplaceText
,ReplaceText
)==0)
357 if(strncmp(SpecialReplace
[Index
].NextText
,Buffer
,Count
)==0)
361 if(SpecialReplace
[Index
].NextText
[Count
]=='\0')
363 if(SpecialReplace
[Index
].SkipCount
)
364 SpecialReplace
[Index
].SkipCount
--;
367 // fprintf(stderr,"%s -> %s ",SpecialReplace[Index].NextText,SpecialReplace[Index].NextReplace);
368 if(SpecialReplace
[Index
].Dupe
)
373 DupeIndex
=1+strlen(strcpy(&DupeBuffer
[1],SpecialReplace
[Index
].NextReplace
));
374 // fprintf(stderr,"[DupeStart]\n");
377 // fprintf(stderr,"[Ignored]\n");
381 fwrite(SpecialReplace
[Index
].NextReplace
,1,strlen(SpecialReplace
[Index
].NextReplace
),stdout
);
387 fread(&Buffer
[Count
++],1,1,stdin
);
388 if(Buffer
[Count
-1]!=SpecialReplace
[Index
].NextText
[Count
-1])
396 fwrite(Buffer
,1,Count
,stdout
);
398 // fprintf(stderr,"...Done SpecialReplace!\n");
404 fwrite(&Prefix
,1,TriggerPtr
-Prefix
,stdout
);
405 fwrite(FileID
,1,8,stdout
);
410 while(LeafLen
<sizeof(LeafName
)-1)
412 fread(&LeafName
[LeafLen
++],1,1,stdin
);
413 if(LeafName
[LeafLen
-1]=='\n')
416 LeafName
[LeafLen
]='\0';
417 fwrite(LeafName
,1,LeafLen
,stdout
);
420 fprintf(stderr
," Replace(\"%s\",\"????\"); // %s",FileID
,LeafName
);
421 Replace(FileID
,Marker
);
426 else if(TriggerStart
==NodePathTrigger
|| TriggerStart
==NextRevTrigger
)
430 fwrite(NodePathTrigger
,1,strlen(NodePathTrigger
),stdout
);
431 fwrite(DupeBuffer
,1,DupeIndex
,stdout
);
432 // fprintf(stderr,"Done Dupe!\n");
435 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
436 NodePathFlag
=(TriggerStart
==NodePathTrigger
);
438 else if(TriggerStart
==NodeRevTrigger
)
442 memcpy(&DupeBuffer
[DupeIndex
],TriggerStart
,TriggerPtr
-TriggerStart
);
443 DupeIndex
+=TriggerPtr
-TriggerStart
;
445 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
450 fread(&Buffer
[i
],1,1,stdin
);
456 else if(Buffer
[i
]<'0' || Buffer
[i
]>'9')
459 fprintf(stderr
,"Non-numeric revision! (starting \"%s\")\n",Buffer
);
464 if(sscanf(Buffer
,"%d\n",&Rev
))
468 else if(RevSubst
[Rev
] && RevSubst
[Rev
]<MaxRevSeen
)
470 i
=sprintf(Buffer
,"%d\n",RevSubst
[Rev
]);
471 fprintf(stderr
,"RevSubst OK: %d -> %s",Rev
,Buffer
);
475 fprintf(stderr
,"sscanf failed!!!\n");
476 fwrite(Buffer
,1,i
,stdout
);
479 memcpy(&DupeBuffer
[DupeIndex
],Buffer
,i
);
486 bool ActionTaken
=false;
487 while(i
<TriggerCount
)
489 // NB strcmp rather than pointer comparison, as there may be multiple matches.
490 if(strcmp(TriggerStart
,Triggers
[i
].TriggerText
)==0)
492 bool RemoveTrigger
=true;
493 switch(Triggers
[i
].Type
)
495 case Type_MoveOrphan
:
498 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
501 Triggers
[i
].Node
->Text
=Triggers
[i
].CopyText
;
503 case Type_SuppressCreate
:
506 if(Triggers
[i
].SkipCount
)
508 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
509 Triggers
[i
].SkipCount
--;
514 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
515 fwrite("-suppressed",1,11,stdout
);
520 fprintf(stderr
,"ActionTaken before a SuppressCreate\nTriggered on '%s', type %d\n",Triggers
[i
].TriggerText
,Triggers
[i
].Type
);
524 case Type_MultiReplace
:
527 case Type_OneShotReplace
:
530 if(Triggers
[i
].SkipCount
)
532 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
533 Triggers
[i
].SkipCount
--;
537 fwrite(Triggers
[i
].CopyText
,1,strlen(Triggers
[i
].CopyText
),stdout
);
541 RemoveTrigger
=false; // could be a second "OneShotReplace" stacked up to make a TwoShotReplace, etc...
546 case Type_OneShotDupe
:
549 if(Triggers
[i
].SkipCount
)
551 Triggers
[i
].SkipCount
--;
556 fprintf(stderr
,"OneShotDupe: %s -> %s\n",Triggers
[i
].TriggerText
,Triggers
[i
].CopyText
);
558 DupeIndex
=1+strlen(strcpy(&DupeBuffer
[1],Triggers
[i
].CopyText
));
560 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
564 RemoveTrigger
=false; // could be a second "OneShotDupe" stacked up to make a TwoShotDupe, etc...
567 // prevent a 'move' from occuring... do this by creating a OneShotReplace so that the
568 // delete action applies to the intended target dir rather than the source dir.
569 // this means that the copy still occurs, as does the delete, but delete has a different target.
572 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
575 Triggers
[i
].Node
=NULL
;
577 register const char *Temp
=Triggers
[i
].CopyText
;
578 Triggers
[i
].CopyText
=Triggers
[i
].TriggerText
;
579 Triggers
[i
].TriggerText
=Temp
;
581 Triggers
[i
].Type
=Type_OneShotReplace
;
586 fprintf(stderr
,"SOMEONE FORGOT TO WRITE THIS BIT!!!!\nTriggered on '%s', type %d\n",Triggers
[i
].TriggerText
,Triggers
[i
].Type
);
591 else if(i
<--TriggerCount
)
592 memmove(&Triggers
[i
],&Triggers
[i
+1],sizeof(*Triggers
)*(TriggerCount
-i
));
598 TriggerPtr
=TriggerStart
=NULL
;
603 if(TriggerPtr
!=TriggerStart
)
605 int CurrentOffset
=TriggerPtr
-TriggerStart
;
606 // look for an alternative trigger starting with the same letter(s)
607 if(strncmp(TriggerStart
,NodeRevTrigger
,CurrentOffset
)==0 &&
608 c
==NodeRevTrigger
[CurrentOffset
])
610 TriggerStart
=NodeRevTrigger
;
611 TriggerPtr
=TriggerStart
+CurrentOffset
;
613 else if(NodePathFlag
)
615 for(int i
=0;i
<TriggerCount
;i
++)
617 if(strncmp(TriggerStart
,Triggers
[i
].TriggerText
,CurrentOffset
)==0 &&
618 c
==Triggers
[i
].TriggerText
[CurrentOffset
] && (Triggers
[i
].Type
!=Type_MoveOrphan
|| Triggers
[i
].Node
->Used
))
620 TriggerStart
=Triggers
[i
].TriggerText
;
621 TriggerPtr
=TriggerStart
+CurrentOffset
;
628 fwrite(TriggerStart
,1,TriggerPtr
-TriggerStart
,stdout
);
631 memcpy(&DupeBuffer
[DupeIndex
],TriggerStart
,TriggerPtr
-TriggerStart
);
632 DupeIndex
+=TriggerPtr
-TriggerStart
;
634 TriggerPtr
=TriggerStart
=NULL
;
640 if(LastSpace
&& c
==Prefix
[0])
641 TriggerPtr
=TriggerStart
=Prefix
;
642 else if(c
==NodePathTrigger
[0])
643 TriggerPtr
=TriggerStart
=NodePathTrigger
;
644 else if(c
==NextRevTrigger
[0])
645 TriggerPtr
=TriggerStart
=NextRevTrigger
;
646 else if(NodePathFlag
)
648 for(int i
=0;i
<TriggerCount
;i
++)
649 if(c
==Triggers
[i
].TriggerText
[0] && (Triggers
[i
].Type
!=Type_MoveOrphan
|| Triggers
[i
].Node
->Used
))
651 TriggerPtr
=TriggerStart
=Triggers
[i
].TriggerText
;
656 if(TriggerPtr
&& c
==*TriggerPtr
)
660 fwrite(&c
,1,1,stdout
);
662 DupeBuffer
[DupeIndex
++]=c
;
669 while(TriggerCount
-->0)
671 fprintf(stderr
,"Unused Trigger: \"%s\" (Type %d, Copy '%s' to %p)\n",
672 Triggers
[TriggerCount
].TriggerText
,Triggers
[TriggerCount
].Type
,Triggers
[TriggerCount
].CopyText
,Triggers
[TriggerCount
].Node
);