|
|
1.1 root 1: /*
2: $VER: RKNOP's __main() 1.2 (06.02.95)
3:
4: Replacement AmigaDOS __main() for SAS/C 6.51.
5:
6: As with the standard __main(), this parses the input command line into the
7: argv array. However, here, the number of arguments is unlimited;
8: additionally, one may specify on the command line a list of arguments in
9: a file using the construction "@filename" (without quotes). The named file
10: will be read and all of the whitespace separated arguments therein will be
11: inserted to the argv array at that point. Since the string parser is written
12: recursively, embedded files may be nested; that is, within one filename
13: referenced on the command line with @, there may be another filename
14: referenced with @. Memory and stack space is the only limit as to how far
15: the nesting may go.
16:
17: Version 1.2 -- this version supports stderr redirection, similar to unix, by
18: specifying &filename (or & filename or &"file name" or & "file name") on the
19: command line. stderr is redirected by opening first calling Close() on what
20: is currently in __ufbs[2].ufbfh (hopefully this simulates the SAS stdio
21: destructor), and then Open()ing the file __ufbs[2].ufbfh with the specified
22: filename.
23:
24: Inspiration by Peter Simons. Rewritten from scratch by Robert Knop using no
25: SAS code so that this file could be freely distributed with PGP 2.6
26: source code.
27:
28: [email protected]
29: [email protected]
30: R.KNOP1 on GEnie
31: */
32:
33: #include <stdlib.h>
34: #include <stdio.h>
35: #include <string.h>
36: #include <ios1.h>
37: #include <dos/dos.h>
38: #include <exec/lists.h>
39: #include <exec/memory.h>
40: #include <exec/nodes.h>
41: #include <libraries/dos.h>
42: #include <libraries/dosextens.h>
43: #include <workbench/startup.h>
44:
45: #include <proto/dos.h>
46: #include <proto/exec.h>
47:
48: #define isspace(c) (((c)==' ')||((c)=='\t')||((c)=='\n'))
49:
50: extern struct WBStartup *_WBenchMsg;
51:
52: int main(int,void *);
53: int __regargs CountArgs(struct MinList *,struct ArgNode *);
54: void __regargs AddArgs(struct ArgNode **,char ***);
55:
56: struct ArgNode {
57: struct MinNode n;
58: int length;
59: char *d;
60: };
61:
62: void __stdargs __main(char *inline)
63: { struct ArgNode n,*cur;
64: struct MinList ArgStrings;
65: int argc,rval;
66: char **argv,**pargv;
67:
68: NewList((struct List *)&ArgStrings);
69: n.d=inline;
70: AddTail((struct List *)&ArgStrings,(struct Node *)&n);
71:
72: if (inline && (argc=CountArgs(&ArgStrings,&n)))
73: { if (!(argv=(char **)calloc(argc+1,sizeof(char *))))
74: /* +1 is for one null element at the end of argv */
75: exit(20);
76: cur=&n;
77: pargv=argv;
78: AddArgs(&cur,&pargv);
79: }
80: else argv=(char **)_WBenchMsg; /* Workbench startup */
81:
82: rval=main(argc,argv);
83:
84: /* Don't worry about cleanup -- we used only calloc & malloc */
85: /* (It's safer this way, so that if the program goes directly to exit()
86: we don't have to worry about missed cleanup.) */
87:
88: exit(rval);
89: }
90:
91: /**********************************************************************/
92: /* CountArgs() -- a recursive function that counts the number of */
93: /* arguments in the string in node.d. If, while */
94: /* counting, it comes across an argument of the form */
95: /* "@filename", it creates a new node on the tail of */
96: /* list, reads the data from the named file */
97: /* into this new node's data, and recursively calls */
98: /* itself to count the arguments in the new read string*/
99: /**********************************************************************/
100:
101: int __regargs CountArgs(struct MinList *list,struct ArgNode *node)
102: { int argc;
103: struct ArgNode *n;
104: char *line,*fstart,fendbuffer;
105: BPTR ifp; /* Only 1 file will be open at a time */
106: static struct FileInfoBlock fib; /* static safe for recursion */
107:
108: argc=0;
109: line=node->d;
110: while (1)
111: { while (isspace(*line)) line++; /* Skip leading whitespace */
112:
113: if (*line=='\0') break;
114:
115: else if (*line=='&') /* Skip a stderr redirect */
116: { ++line;
117: while (isspace(*line)) ++line;
118: if (*line=='"')
119: { line++;
120: while (*line!='"' && *line!='\0') line++;
121: if (*line=='"') line++;
122: }
123: else
124: { while (!isspace(*line))
125: { if (*line=='\0') break;
126: ++line;
127: }
128: }
129: }
130:
131: else if (*line=='@') /* Embedded file */
132: { fstart=++line;
133: if (*line=='"')
134: { fstart++; line++;
135: while (*line!='"')
136: if (*(++line)=='\0') break; /* Errorish? */
137: fendbuffer=*line;
138: *line='\0'; /* Temporarily 0-term so we can use as a filename */
139: }
140: else
141: { while (!isspace(*line))
142: if (*(++line)=='\0') break; /* Error? */
143: fendbuffer=*line;
144: *line='\0'; /* Temp 0-term for filename */
145: }
146: if (!(ifp=Open(fstart,MODE_OLDFILE)))
147: fprintf(stderr,"Couldn't open file \"%s\"\n",fstart);
148: else
149: { ExamineFH(ifp,&fib);
150: n=(struct ArgNode *)calloc(sizeof(struct ArgNode),1);
151: /* CHECK ERRORS!!!!!!!!!!! */
152: AddTail((struct List *)list,(struct Node *)n);
153: if (fib.fib_Size)
154: { n->d=calloc((n->length=fib.fib_Size+1),1);
155: Read(ifp,n->d,fib.fib_Size);
156: n->d[fib.fib_Size]='\0'; /* Make sure null terminated */
157: }
158: Close(ifp);
159: if (n->d) argc+=CountArgs(list,n); /* Recurse */
160: }
161: *line=fendbuffer; /* Restore char replaced with '\0' */
162: if (*line=='"') ++line; /* Increment line past quote */
163: } /* End of embedded file handling */
164:
165: else if (*line=='"')
166: { ++line;
167: while (*line!='"')
168: if (*(++line)=='\0') break;
169: argc++;
170: if (*line='"') ++line;
171: }
172:
173: else
174: { while (!isspace(*line))
175: if (*(++line)=='\0') break;
176: argc++;
177: }
178:
179: } /* End of infinite loop */
180:
181: return(argc); /* Also returns any nodes added to list from embed files */
182: }
183:
184: /**********************************************************************/
185: /* AddArgs() -- put each of the arguments in the node into the array */
186: /* argv. Recurse if necessary */
187: /**********************************************************************/
188:
189: void __regargs AddArgs(struct ArgNode **node,char ***argv)
190: { char *line,*stderrfile;
191:
192: line=(*node)->d;
193: (*node)=(struct ArgNode*)(*node)->n.mln_Succ;
194: while (1)
195: { while (isspace(*line)) line++; /* Skip leading whitespace */
196:
197: if (*line=='\0') break; /* Finished */
198:
199: else if (*line=='&') /* stderr redirect */
200: { ++line;
201: while (isspace(*line)) ++line;
202: if (*line=='"')
203: { stderrfile=++line;
204: while (*line!='"' && *line!='\0') line++;
205: if (*line=='"') { *line='\0'; line++; }
206: }
207: else
208: { stderrfile=line;
209: while (!isspace(*line))
210: { if (*line=='\0') break;
211: line++;
212: }
213: if (*line!='\0') { *line='\0'; line++; }
214: }
215: Close(__ufbs[2].ufbfh);
216: if ((__ufbs[2].ufbfh=Open(stderrfile,MODE_NEWFILE))==NULL)
217: __ufbs[2].ufbfh=Open("NIL:",MODE_OLDFILE);
218: }
219:
220: else if (*line=='@') /* Embedded file -- skip past filename */
221: { ++line;
222: if (*line=='"')
223: { while (*line!='"')
224: if (*(++line)=='\0') break;
225: }
226: else
227: { while (!isspace(*line))
228: if (*(++line)=='\0') break;
229: }
230: AddArgs(node,argv); /* Add the arguments from whatever node */
231: if (*line!='\0') ++line;
232: }
233:
234: else if (*line=='"')
235: { (*argv)[0]=++line;
236: while (*line!='"')
237: if (*(++line)=='\0') break;
238: if (*line!='\0')
239: { *line='\0'; /* Null terminate this argument */
240: ++line;
241: }
242: (*argv)++;
243: }
244:
245: else
246: { (*argv)[0]=line;
247: while (!isspace(*line))
248: if (*(++line)=='\0') break;
249: if (*line!='\0')
250: { *line='\0'; /* Null terminate this argument */
251: ++line;
252: }
253: (*argv)++;
254: }
255: } /* End of infinite loop */
256: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.