source: projects/puncher/frontend.cli.c @ 8

Last change on this file since 8 was 8, checked in by sven, 11 years ago

Puncher subsystem development. The Linux and dummy backends should work right
now, the cli frontend should work, too. GTK frontend still in development.
Windows backend still... in preparation ;-)

-- Sven @ workstation

File size: 6.7 KB
Line 
1/**
2 * The Paper Tape Project -- Punching subsystem
3 * CLI Frontend implementation
4 *
5 * This is a very simple cross-platform stand alone command
6 * line interface, with basic features (no [n]curses, etc.),
7 * like the old "userspace-driver" had them. This includes:
8 *
9 *  * Reading bytes from stdin and transfering to the backend
10 *  * Accepting some command line arguments for setting the file
11 *    size (how much bytes we can await at stdin) or switching
12 *    on DEBUG mode.
13 *  * Giving a very simple progress output: For every byte
14 *    one line.
15 *
16 * (c) 2008 Sven Köppel
17 *
18 **/
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <unistd.h> /* Problematisch auf Windows! */
23#include <errno.h>
24#include <stdarg.h> /* var argument list */
25#include <math.h>
26
27#include "backend.h"
28
29#define DPRINTF(bla...) { if(debug_flag) fprintf(stderr,bla); }
30int debug_flag; /* global var. */
31
32void puncher_frontend_visualize_byte(unsigned char buf);
33void puncher_frontend_calculate_time(int already_punched_bytes, int estimated_punch_length, int mtime_since_beginning);
34
35// We need a portable function for this one!
36int puncher_frontend_mtime(long long since) {
37        /* gibt millisekunden zurueck seit since. since sind dabei die
38           Millisekunden seit der Unix-Epoche. Ein initiales since kann
39           per mtime(0) gefunden werden. */
40        struct timeval time;
41        gettimeofday(&time, NULL);
42              // Sec*10^6
43        return (time.tv_sec * 1000000 + time.tv_usec) - since;
44}
45
46int main(int argc, char **argv) {
47        long long time_since_beginning; // measuring time.
48        int already_punched = 0; // Anzahl bereits gepunchte bytes
49        int estimated_data_length = 0; // per Schalter -l angegebbare Datenlaenge
50        size_t ret; // multi purpose return value
51       
52        printf("The Paper Tape Project -- Punching subsystem\n");
53        printf("Cross Plattform Command line interface\n");
54        printf("time ms |123.45678|  hex=dec status: =) punch successful / :-( still busy\n");
55       
56        // Starting of parsing program arguments
57        debug_flag = 0;
58        opterr = 0;
59        int c;
60        while( (c = getopt(argc, argv, "dhl:s:")) != -1)
61            switch(c) {
62                case 'd':
63                    debug_flag = 1;
64                    break;
65                case 'h':
66                    fprintf(stderr, "Usage: %s [-d] [-h] [-lNUM]\n"
67                      "  optional parameters:\n"
68                      "   -d   debug mode, print out verbose informations about signals\n"
69                      "        if not set, only normal verbosity will be printed out on\n"
70                      "        stdout, painting an ASCII paper tape which visualizes the\n"
71                      "        bytes (see above for the caption)\n\n"
72                      "   -h   display this help message\n\n"
73                      "   -s   same as -l\n"
74                      "   -l   sets the NUMBER OF BYTES which are expected on stdin.\n"
75                      "        with this information we can complete the status information\n"
76                      "        with useful informations about the estimated remaining time\n"
77                      "        to punch (useful for longer data)\n"
78                      "        example: cat 2k-data-file | %s -l2000\n",
79                      argv[0], argv[0]);
80                    return 0;
81                case 'l':
82                case 's':
83                    c = atoi(optarg);
84                    if( c > 0 ) {
85                        estimated_data_length = c;
86                        break;
87                    }
88                    printf("%s: data length must be a positive integer, like '123', not %s\n", argv[0], optarg);
89                case '?': break;
90            }
91        // end of parsing program arguments
92
93        // initializing backend...
94        PuncherBackend* puncher;
95        if(! (puncher = puncher_backend_new(debug_flag)) ) {
96                perror("creating puncher backend");
97        }
98
99        /* The main loop (reading stdin and printing out) */
100        /* We will just read 1 byte at one time to handle
101         * it nicely... */
102        DPRINTF("Start reading from stdin...\n");
103        time_since_beginning = puncher_frontend_mtime(0);
104        for(;;) {
105                unsigned char buf; /* stdin 1 byte buffer */
106
107                ret = read(0, &buf, 1); /* 1 byte from stdin */
108                if(ret < 0) {
109                        perror("read stdin");
110                        puncher_backend_destroy(puncher);
111                        return 1;
112                }
113
114                if(ret == 0) {/* EOF, end of input, etc. */
115                        DPRINTF("stdin EOF\n");
116                        break;
117                }
118
119                /* Visualisation of the byte in a stdout line */
120                printf("%5ims ", (int)(puncher_frontend_mtime(time_since_beginning)/1000));
121                puncher_frontend_visualize_byte(buf);
122                printf(" 0x%02x=%03i ", buf, buf);
123                puncher_frontend_calculate_time(++already_punched, estimated_data_length, (int)(puncher_frontend_mtime(time_since_beginning)/1000));
124
125                /* call the backend */
126                ret = puncher_backend_write_byte(puncher, buf);
127                if(ret < 0) {
128                        perror("calling write backend");
129                        puncher_backend_destroy(puncher);
130                        return 1;
131                } else if(ret == 0) {
132                        printf("=)\n"); // everything okay
133                } else if(ret == 1) {
134                        printf(":-(\n"); // punch not okay, but go on.
135                }
136        } /* for stdin */
137
138        DPRINTF("Transmission finished\n");
139        if(puncher_backend_destroy(puncher)) {
140                perror("finishing backend");
141                return 1;
142        } else
143                return 0;
144}
145
146void puncher_frontend_visualize_byte(unsigned char buf) {
147        /* Draw a papertape byte (like the perl program) */
148        unsigned char against = 0x01;
149        unsigned char check;
150        int pos;
151       
152        printf("|");
153        for(pos=0; pos < 8; pos++) {
154                if(pos == 3) /* Streifenfuehrung */
155                        printf(".");
156                check = buf;
157                check >>= pos;
158               
159                if((check & against) == 0)
160                        printf(" "); /* bit nicht gesetzt */
161                else
162                        printf("*"); /* bit gesetzt */
163        } /*for */
164        printf("|");
165}
166
167
168void puncher_frontend_calculate_time(int already_punched_bytes, int estimated_punch_length, int mtime_since_beginning) {
169        /* In jeder Zeile berechnen, wie lange noch gepuncht wird,
170         * und ausgeben. Nur wenn Laenge per "-l" oder "-s" angegeben
171         * wird. In Bytes.
172         *
173         * Irgendwie ist der Berechnungsalgorithmus etwas schrottig und
174         * produziert in den ersten Sekunden nur Müll, aber ansonsten
175         * ist er ganz okay.
176         */
177        int percentage, remaining_sec = 0;
178         
179        if(!estimated_punch_length) return; // wenn es gar nicht abgegeben wurde
180       
181        //printf("%i %i ", already_punched_bytes, estimated_punch_length, mtime_since_beginning);
182       
183        percentage = (int)rint(((float)already_punched_bytes / (float)estimated_punch_length) * 100);
184        if(mtime_since_beginning != 0) // erst nach dem ersten Zyklus berechenbar
185            remaining_sec = (int)rint(((float)mtime_since_beginning / ((float)already_punched_bytes / (float)estimated_punch_length) - mtime_since_beginning)/1000);
186       
187        if(already_punched_bytes <= estimated_punch_length) {
188               printf("| %i%% (%i sec remaining)  ", percentage, remaining_sec);
189        }
190}
Note: See TracBrowser for help on using the repository browser.
© 2008 - 2013 technikum29 • Sven Köppel • Some rights reserved
Powered by Trac
Expect where otherwise noted, content on this site is licensed under a Creative Commons 3.0 License