home *** CD-ROM | disk | FTP | other *** search
- /*
- * Concat - concatenate and print files.
- * AmigaDOS equivalent of UNIX System V cat.
- *
- * Version 37.1 =TP= 28-Jan-92
- *
- * Compile with SAS/C 5.10a and link without startup code:
- * lc -cqfist -v -b0 -rr -O -ms Concat
- * blink Concat.o to Concat sd sc
- * protect Concat +p
- *
- * Copyright (c) 1992 Torsten Poulin
- *
- * Torsten Poulin
- * Banebrinken 99, 2, lejlighed 77
- * DK 2400 København NV
- * DENMARK
- */
-
- /****** English:CONCAT ****************************************************
- *
- * FORMAT
- * CONCAT [[FROM] <files|patterns>] [TO <name>]
- * [SORT] [QUIET] [VISIBLE [TABS] [EOL]] [UNBUF]
- *
- * TEMPLATE
- * FROM/M,TO/K,SORT/S,QUIET/S,VISIBLE/S,TABS/S,EOL/S,UNBUF/S
- *
- * PURPOSE
- * To concatenate and print files.
- *
- * SPECIFICATION
- * Concat reads each of the specified FROM files and writes it
- * to the destination specified by the TO option. If no FROM
- * option is given Concat reads from its default input; likewise
- * if no TO option is specified it writes to its default output.
- *
- * The following switches apply to Concat.
- *
- * SORT The FROM files are read in alphabetical order.
- * Useful when concatenating files split with Split.
- *
- * QUIET Concat is quiet about non-existent input files.
- *
- * VISIBLE Causes non-printing characters (with the exception
- * of tabs and new-lines) to be printed visibly.
- * Control characters are printed as ^X (control-x);
- * the DEL character (hex 0x7d) is printed as ^?.
- * Non-ASCII characters (with the high bit set) are
- * printed as M-x, where x is the character specified
- * by the seven low order bits.
- *
- * UNBUF The output is not buffered. (The default is
- * buffered output.)
- *
- * When used with the VISIBLE switch, the following switches
- * may be used.
- *
- * TABS Causes tabs to be printed as ^I's.
- *
- * EOL Causes a $ character to be printed at the end of
- * each line (prior to the new-line).
- *
- * The TABS and EOL switches are ignored if the VISIBLE
- * switch is not specified.
- *
- * SEE ALSO
- * COPY, JOIN, MORE, SPLIT, TYPE
- *
- ***************************************************************************
- *
- */
- /****** dansk:CONCAT ******************************************************
- *
- * FORMAT
- * CONCAT [[FROM] <filer|mønstre>] [TO <navn>]
- * [SORT] [QUIET] [VISIBLE [TABS] [EOL]] [UNBUF]
- *
- * SKABELON
- * FROM/M,TO/K,SORT/S,QUIET/S,VISIBLE/S,TABS/S,EOL/S,UNBUF/S
- *
- * FORMÅL
- * At sammenkæde og udskrive filer.
- *
- * SPECIFIKATION
- * Concat læser hver af de med FROM angivne filer og skriver
- * dem til destinationen angivet af TO. Hvis der ikke er
- * angivet nogen FROM-filer, læser Concat fra sit standard-
- * input. Ligeledes skriver den til sit standardoutput hvis
- * der ikke er angivet en destination med TO.
- *
- * Følgende kontakter kan bruges med Concat:
- *
- * SORT FROM-filerne læses i alfabetisk orden. Nyttigt
- * ved sammenkædning af filer splittet med SPLIT.
- *
- * QUIET Concat tier stille om ikke-eksisterende filer.
- *
- * VISIBLE Usynlige tegn (med undtagelse af tabulerings- og
- * ny-linjetegn) bliver udskrevet synligt.
- * Styretegn udskrives som ^X (kontrol-x).
- * Slettetegnet (heksadecimalt 0x7d) udskrives som
- * ^?. Ikke-ASCII-tegn (med mest betydende bit sat)
- * udskrives som M-x, hvor x er tegnet givet ved de
- * syv mindst betydende bit.
- *
- * UNBUF Uddata bliver ikke bufferet. (Standard er bufferet
- * uddata.)
- *
- * Når kontakten VISIBLE er angivet kan følgende kontakter
- * bruges:
- *
- * TABS Tabuleringstegn udskrives som ^I'er.
- *
- * EOL Et $-tegn udskrives i slutningen af hver linje (før
- * ny-linjetegnet).
- *
- * Kontakterne TABS og EOL bliver ignoreret hvis kontakten
- * VISIBLE ikke er angivet.
- *
- * SE OGSÅ
- * COPY, JOIN, MORE, SPLIT, TYPE
- *
- ***************************************************************************
- *
- */
-
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <dos/dos.h>
- #include <dos/dosasl.h>
- #include <clib/dos_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #include <stdio.h>
- #include <string.h>
-
- #ifdef __SASC
- #include <pragmas/dos_pragmas.h>
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/intuition_pragmas.h>
- #pragma libcall UtilityBase Stricmp A2 9802
- #endif
-
- /* my include files are for early V36, so ... */
- LONG Stricmp(char *, char *);
-
- /* !!! Assumption: DOS used to be in BCPL, so max length is 256(?) */
- #define MAXNAMELEN 256L
-
- #define TEMPLATE "FROM/M,TO/K,SORT/S,QUIET/S,VISIBLE/S,TABS/S,EOL/S,UNBUF/S"
- #define OPT_FROM 0
- #define OPT_TO 1
- #define OPT_SORT 2
- #define OPT_QUIET 3
- #define OPT_VISIBLE 4
- #define OPT_TABS 5
- #define OPT_EOL 6
- #define OPT_UNBUF 7
-
-
- static VOID myFPutC(struct DosLibrary *, BPTR, LONG, BOOL);
- static LONG doConcat(struct Library *, struct DosLibrary *,
- BPTR, BPTR, BOOL, BOOL, BOOL, BOOL);
-
- typedef struct nameList {
- struct nameList *next;
- UBYTE *name;
- } nameList;
-
- char const *blurp = "\0$VER: Concat 37.1 (28.1.92) ©1992 Torsten Poulin";
-
-
- LONG entrypoint(VOID)
- {
- struct Library *SysBase;
- struct DosBase *DOSBase;
- struct IntuitionBase *IntuitionBase;
- struct Library *UtilityBase;
- struct RDArgs *args;
- struct AnchorPath *ap;
- struct Remember *rememberkey;
- nameList *list, *p;
- LONG arg[8];
- LONG rc = RETURN_OK;
- UBYTE **fromfiles;
- ULONG i;
- BPTR in, out;
-
- SysBase = *(struct Library **) 4L;
- if(!(DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37L)))
- goto noDOS;
- if(!(IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 33L)))
- goto noIntuition;
- if(!(UtilityBase = OpenLibrary("utility.library", 37L)))
- goto noUtility;
-
- arg[OPT_FROM] = arg[OPT_TO] = arg[OPT_SORT] = arg[OPT_QUIET] =
- arg[OPT_VISIBLE] = arg[OPT_TABS] = arg[OPT_EOL] = arg[OPT_UNBUF] = 0L;
-
- if(args = ReadArgs(TEMPLATE, arg, NULL))
- {
- out = NULL;
- if(arg[OPT_TO] && !(out = Open((UBYTE *) arg[OPT_TO], MODE_NEWFILE)))
- {
- LONG err = IoErr();
- PutStr("Concat can't open ");
- PrintFault(err, (UBYTE *) arg[OPT_TO]);
- rc = RETURN_ERROR;
- goto exitProgram;
- }
-
- if(arg[OPT_FROM])
- {
- rememberkey = NULL;
- list = NULL;
-
- fromfiles = (UBYTE **) arg[OPT_FROM];
- for(i = 0; fromfiles[i]; i++)
- {
- UBYTE *dummy;
- LONG IsWild;
-
- if(!(ap = (struct AnchorPath *)
- AllocRemember(&rememberkey,
- sizeof(struct AnchorPath) + MAXNAMELEN,
- MEMF_PUBLIC | MEMF_CLEAR)))
- {
- PrintFault(ERROR_NO_FREE_STORE, "Concat");
- rc = RETURN_FAIL;
- goto exitProgram;
- }
-
- ap->ap_Strlen = MAXNAMELEN;
-
- /* Kludge to determine if it's pattern */
- if(!(dummy = AllocMem(2 * strlen(fromfiles[i]) + 2,
- MEMF_PUBLIC)))
- {
- PrintFault(ERROR_NO_FREE_STORE, "Concat");
- rc = RETURN_FAIL;
- goto exitProgram;
- }
- IsWild = ParsePattern(fromfiles[i], dummy,
- 2 * strlen(fromfiles[i]) + 2);
- FreeMem(dummy, 2 * strlen(fromfiles[i]) + 2);
- if(IsWild == -1)
- {
- LONG err = IoErr();;
- PrintFault(err, "Concat");
- rc = RETURN_FAIL;
- goto exitProgram;
- }
-
- if(!IsWild || MatchFirst(fromfiles[i], ap) == 0)
- do
- {
- nameList *newnode, *p;
- UBYTE *insertname;
-
- /*
- if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
- {
- PrintFault(ERROR_BREAK, NULL);
- rc = RETURN_WARN;
- if(IsWild)
- MatchEnd(ap);
- goto exitProgram;
- }
- */
-
- if(IsWild)
- {
- insertname = ap->ap_Buf;
- if(ap->ap_Info.fib_DirEntryType > 0)
- continue;
- }
- else
- insertname = fromfiles[i];
-
- /* File names are stored in an ordered linked list
- * unless arg[OPT_SORT] is FALSE in which case
- * they are inserted at the end of the list.
- */
-
- if(!(newnode = (nameList *)
- AllocRemember(&rememberkey, sizeof(nameList),
- MEMF_PUBLIC)))
- {
- PrintFault(ERROR_NO_FREE_STORE, "Concat");
- rc = RETURN_FAIL;
- goto noMemory1;
- }
- if(!(newnode->name = (UBYTE *)
- AllocRemember(&rememberkey,
- strlen(insertname) + sizeof(UBYTE),
- MEMF_PUBLIC)))
- {
- PrintFault(ERROR_NO_FREE_STORE, "Concat");
- rc = RETURN_FAIL;
- goto noMemory1;
- }
- strcpy(newnode->name, insertname);
- newnode->next = NULL;
-
- if(list == NULL) /* insert into empty list */
- list = newnode;
- else
- {
- /* inserting into nonempty list */
- p = list;
-
- if(Stricmp(insertname, p->name) < 0
- && arg[OPT_SORT])
- {
- /* insert before first node */
- newnode->next = list;
- list = newnode;
- }
- else
- {
- /* general case */
- for(; p->next; p = p->next)
- if(Stricmp(insertname, p->next->name) < 0
- && arg[OPT_SORT])
- break;
- newnode->next = p->next;
- p->next = newnode;
- }
- }
- } while(IsWild == 1 && MatchNext(ap) == 0);
- noMemory1:
- if(IsWild)
- MatchEnd(ap);
- }
-
- /* Output by running through list of file names */
- for(p = list; p; p = p->next)
- {
- if(in = Open(p->name, MODE_OLDFILE))
- {
- rc = doConcat(SysBase, DOSBase,
- in, arg[OPT_TO] ? out : Output(),
- arg[OPT_VISIBLE], arg[OPT_TABS],
- arg[OPT_EOL], arg[OPT_UNBUF]);
- Close(in);
- if(rc != 0)
- break;
- }
- else
- {
- LONG err = IoErr();
- if(!arg[OPT_QUIET])
- {
- PutStr("Concat can't open ");
- PrintFault(err, p->name);
- }
- }
- }
- FreeRemember(&rememberkey, TRUE);
- }
- else
- {
- /* Reading from default input */
- rc = doConcat(SysBase, DOSBase,
- Input(), arg[OPT_TO] ? out : Output(),
- arg[OPT_VISIBLE], arg[OPT_TABS],
- arg[OPT_EOL], arg[OPT_UNBUF]);
- }
- exitProgram:
- if(out)
- Close(out);
- FreeArgs(args);
- }
- else
- {
- LONG err = IoErr();
- PrintFault(err, "Concat");
- rc = RETURN_ERROR;
- }
-
- CloseLibrary(UtilityBase);
- noUtility:
- CloseLibrary((struct Library *) IntuitionBase);
- noIntuition:
- CloseLibrary((struct DosBase *) DOSBase);
- noDOS:
- return rc;
-
- /*
- * Yes, I KNOW this function is t o o l o n g
- * and contains far too many goto's ;-)
- */
- }
-
-
-
- static LONG doConcat(struct Library *SysBase, struct DosLibrary *DOSBase,
- BPTR in, BPTR out,
- BOOL visible, BOOL tabs, BOOL eol, BOOL unbuf)
- {
- register UBYTE breakcheck = 0;
- LONG c;
-
- while((c = FGetC(in)) != -1)
- {
- if(visible)
- {
- if(eol && c == '\n')
- myFPutC(DOSBase, out, '$', unbuf);
- else if(tabs && c == '\t')
- {
- myFPutC(DOSBase, out, '^', unbuf);
- c = 'I';
- }
- else if(c >= 0x80)
- {
- myFPutC(DOSBase, out, 'M', unbuf);
- myFPutC(DOSBase, out, '-', unbuf);
- c &= 0x7f;
- }
- if((c < ' ' && c != '\t' && c != '\n') || c == 0x7F)
- {
- myFPutC(DOSBase, out, '^', unbuf);
- if(c == 0x7F)
- c = '?';
- else
- c += 'A' - 1;
- }
- }
- myFPutC(DOSBase, out, c, unbuf);
- if(!(breakcheck -= 8) && SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
- {
- PrintFault(ERROR_BREAK, NULL);
- return RETURN_WARN;
- }
- }
- return 0L;
- }
-
-
- static VOID myFPutC(struct DosLibrary *DOSBase, BPTR out, LONG c, BOOL nobuf)
- {
- if(nobuf)
- Flush(out);
- FPutC(out, c);
- }
-