WIP "R" clone. Only argument parsing is working.
[AROS.git] / workbench / c / R / main.c
blob3fc1d1a9b29f820d2f957a76034a7739ff66e6b8
1 /*
2 Copyright © 2012, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <proto/exec.h>
7 #include <proto/dos.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <ctype.h>
14 #define DEBUG 1
15 #include <aros/debug.h>
17 #include "r.h"
19 #define ARG_TEMPLATE "FILENAME,PROFILE/K,NOGUI/S,ARGUMENTS/F"
21 enum
23 ARG_FILENAME,
24 ARG_PROFILE,
25 ARG_NOGUI,
26 ARG_ARGUMENTS,
27 ARG_COUNT
30 // functions
31 static void clean_exit(struct Req *req, CONST_STRPTR s)
33 LONG retval = RETURN_OK;
35 if (s)
37 retval = RETURN_FAIL;
38 PutStr(s);
40 if (req)
42 if (req->rda) FreeArgs(req->rda);
43 FreeVec(req);
46 exit(retval);
49 static struct Req *alloc_req(void)
51 return AllocVec(sizeof (struct Req), MEMF_ANY | MEMF_CLEAR);
54 static BOOL handle_args(struct Req *req, int argc, char **argv)
56 if (argc)
58 IPTR args[ARG_COUNT] = {0};
60 req->rda = ReadArgs(ARG_TEMPLATE, args, NULL);
61 if (!req->rda)
63 PrintFault(IoErr(), argv[0]);
64 return FALSE;
67 req->filename = (STRPTR)args[ARG_FILENAME];
68 req->profile = (STRPTR)args[ARG_PROFILE];
69 req->nogui = args[ARG_NOGUI] ? TRUE : FALSE;
70 req->arguments = (STRPTR)args[ARG_ARGUMENTS];
72 else
74 return FALSE;
75 // FIXME: it should be possible to use R as default tool
76 // of another command
78 return TRUE;
81 static BOOL get_template(struct Req *req)
83 BOOL retval = FALSE;
85 BPTR input_fh = NULL;
86 BPTR output_fh = NULL;
88 TEXT out_file_name[30];
89 TEXT in_file_name[30];
91 TEXT cmd[255];
93 LONG i;
94 LONG cmd_res = 0;
96 if (req->filename == NULL)
98 goto cleanup;
101 for (i = 0; i < 20 && output_fh == NULL; i++)
103 sprintf(out_file_name, "t:%08u.request.outfile", i);
104 output_fh = Open(out_file_name, MODE_NEWFILE);
106 if (output_fh == NULL)
108 goto cleanup;
111 for (i = 0; i < 20 && input_fh == NULL; i++)
113 sprintf(in_file_name, "t:%08u.request.infile", i);
114 input_fh = Open(in_file_name, MODE_NEWFILE);
116 if (input_fh == NULL)
118 goto cleanup;
120 Close(input_fh);
121 input_fh = Open(in_file_name, MODE_OLDFILE);
122 if (input_fh == NULL)
124 goto cleanup;
127 // append "*>NIL: ?" to the command
128 strlcpy(cmd, req->filename, sizeof cmd);
129 strlcat(cmd, " *>NIL: ?", sizeof cmd);
131 // shut up DOS error message
132 struct Process *me = (struct Process*)FindTask(NULL);
133 APTR oldwin = me->pr_WindowPtr;
134 me->pr_WindowPtr = (APTR)-1;
136 // Execute the command
137 cmd_res = Execute(cmd, input_fh, output_fh);
138 D(bug("[R] Execute() returned: %d\n", cmd_res));
140 // restore window ptr
141 me->pr_WindowPtr = oldwin;
143 // go to the beginning of the output file and read the template
144 Seek(output_fh, 0, OFFSET_BEGINNING);
145 if (FGets(output_fh, req->cmd_template, sizeof req->cmd_template))
147 D(bug("[R] template read: %s\n", req->cmd_template));
148 retval = TRUE;
151 cleanup:
152 if (input_fh)
154 Close(input_fh);
155 DeleteFile(in_file_name);
157 if (output_fh)
159 Close(output_fh);
160 DeleteFile(out_file_name);
163 return retval;
167 static BOOL parse_template(struct Req *req)
169 TEXT *chr = req->cmd_template;
170 LONG len;
172 if (req->cmd_template[0] == '\0')
173 return FALSE;
175 while (req->arg_cnt < MAX_ARG_CNT)
177 // read name
178 TEXT *name_start = chr;
179 while (isalnum(*chr) || *chr == '=')
180 chr++;
182 len = chr - name_start;
183 if (len == 0)
184 return FALSE;
186 if (len >= MAX_NAME_CNT - 1)
187 len = MAX_NAME_CNT - 1;
189 memcpy(req->cargs[req->arg_cnt].argname, name_start, len);
191 // read modifiers
192 while (*chr == '/')
194 switch (*(chr + 1))
196 case 'A':
197 req->cargs[req->arg_cnt].a_flag = TRUE;
198 chr++;
199 break;
200 case 'F':
201 req->cargs[req->arg_cnt].f_flag = TRUE;
202 chr++;
203 break;
204 case 'K':
205 req->cargs[req->arg_cnt].k_flag = TRUE;
206 chr++;
207 break;
208 case 'M':
209 req->cargs[req->arg_cnt].m_flag = TRUE;
210 chr++;
211 break;
212 case 'N':
213 req->cargs[req->arg_cnt].n_flag = TRUE;
214 chr++;
215 break;
216 case 'S':
217 req->cargs[req->arg_cnt].s_flag = TRUE;
218 chr++;
219 break;
220 default:
221 return FALSE;
222 break;
224 chr++;
226 req->arg_cnt++;
227 if (*chr != ',')
228 break;
229 chr++;
231 return TRUE;
234 static void execute_command(void)
240 int main(int argc, char **argv)
242 struct Req *req = alloc_req();
243 if (req == NULL)
244 clean_exit(req, "Can't allocate struct Req\n");
246 if (! handle_args(req, argc, argv))
247 clean_exit(req, "Failed to parse arguments\n");
249 if (! get_template(req))
250 clean_exit(req, "Failed to get template\n");
252 if (! parse_template(req))
253 clean_exit(req, "Failed to parse the template\n");
255 create_gui(req);
257 execute_command();
259 clean_exit(req, NULL);
261 return RETURN_OK;