|
Appunti informatica |
|
Visite: 1700 | Gradito: | [ Picolo appunti ] |
Leggi anche appunti:Vettori di interrupt o puntatori?Vettori di interrupt o puntatori? Degli interrupt e dei loro vettori si parla Le variabiliLe variabili E' il momento di ripescare CIAO.C e complicarlo un poco. #include Problemi di cooperazione nel modello a scambio di messaggiProblemi di cooperazione nel modello a scambio di messaggi VIII) Scrivere |
Perdersi in un groviglio di drive e directory non è una bella esperienza. Per questo è opportuno che un programma possa sapere, se necessario, qual è l'attuale directory di lavoro. La libreria del C Borland mette a disposizione due funzioni che forniscono informazioni al proposito: getcurdir(), che permette di conoscere la directory corrente per un dato drive (compreso quello di default), e getcwd(), che consente di conoscere la directory corrente del drive di default. Come si può facilmente constatare, esse sono piuttosto simili e inoltre, dato l'algoritmo utilizzato , vengono entrambe influenzate dai comandi SUBST e JOIN del DOS. Ad esempio, dopo avere assegnato al path C:LAVOROGRAFICA l'identificativo di drive K: mediante SUBST, possiamo referenziare la directory GRAFICA sia come sottodirectory di C:LAVORO, sia come root del drive fittizio K: e posizionarci in essa con il comando CHDIR su C: oppure cambiando in K: il drive di default. In questo caso getcurdir() e getcwd() indicano che la directory corrente è la root di K:. Se il programma necessita conoscere la reale directory di lavoro, ignorando eventuali combinazioni di SUBST e JOIN, può ricorrere al servizio 60h dell'int 21h (descrizione dettagliata a pag. ). Vediamone un esempio di utilizzo:
BARNINGA_Z! - 1991
GETRDIR.C - getrealdir()
int cdecl getrealdir(char *userpath);
char *userpath; puntatore ad array di caratteri allocato a cura
del programmatore e di grandezza sufficiente a
contenere il pathname completo della directory
corrente
Restituisce: 0 se tutto o.k.
0 se si e' verificato un errore
COMPILABILE CON TURBO C++ 1.0
tcc -O -d -rd -c -mx getrdir.c
dove -mx puo' essere -mt -ms -mc -mm -ml -mh
#include <dos.h>
#include <string.h>
#define MAXPATH 80
int cdecl getrealdir(char *userpath)
return(retcode);
L'array realpath funge da buffer sia di input che di output; occorre dunque caricare i registri DS e ES con il suo indirizzo di segmento, e i registri SI e DI con il suo offset. In quanto variabile automatica, realpath è allocato nello stack: il suo indirizzo di segmento è dunque rappresentato dal registro SS; in quanto array, il suo offset è rappresentato dal nome stesso (che è un puntatore all'array). Il valore di SS è ricavato mediante la funzione di libreria segread(), che copia i valori dei registri di segmento nei campi della struttura sregs (di tipo SREGS SI e DI sono caricati, attraverso la union regs di tipo REGS, con l'offset dell'array; il cast ad unsigned è necessario in quanto realpath è puntatore a char, cioè di tipo char *. Se la funzione di libreria intdosx() non ha riscontrato la restituzione di un errore da parte dell'int 21h, da essa invocato, il campo .x.cflag della union REGS è nullo : la stringa preparata dal servizio 60h è copiata all'indirizzo passato come parametro a getrealdir(), che restituisce . Se .x.cflag non è nullo allora getrealdir() restituisce il codice di errore riportato dall'int 21h. Si noti che il puntatore userpath, parametro della funzione, deve essere allocato a cura della routine che invoca la getrealdir() e deve essere in grado di contenere l'intero pathname (la massima lunghezza di un pathname, in DOS, è 80 caratteri compreso il terminatore nullo
Poche modifiche sono sufficienti per trasformare getrealdir() in una funzione in grado di risolvere in pathname completo qualunque nome di file o directory passatole come parametro.
BARNINGA_Z! - 1991
RSLVPATH.C - resolvepath()
int cdecl resolvepath(char *userpath);
char *userpath; puntatore alla stringa contenente il pathname
parziale da risolvere in pathname completo. Lo
spazio allocato deve essere sufficiente a
contenere quest'ultimo.
Restituisce: 0 se tutto o.k.
!0 se si e' verificato un errore:
2 = userpath contiene caratteri non leciti in
un pathname
3 = drive specificato in userpath non valido
COMPILABILE CON TURBO C++ 1.0
tcc -O -d -rd -c -mx RSLVPATH.c
dove -mx puo' essere -mt -ms -mc -mm -ml -mh
#include <dos.h>
#include <string.h>
#define MAXPATH 80
int cdecl resolvepath(char *userpath)
return(retcode);
La differenza sostanziale tra le due funzioni è che resolvepath() utilizza userpath come buffer di input per il servizio 60h. Esso punta ad un array allocato nel segmento dati; pertanto la sua gestione varia a seconda del modello di memoria prescelto per la compilazione. Se lo heap è limitato a 64Kb (modelli tiny, small e medium), userpath esprime un offset rispetto a DS segread() carica dunque sregs.ds con il valore effettivamente necessario all'int 21h. Nei modelli compact, large e huge userpath è un puntatore far: si rende pertanto necessario l'uso delle macro FP_SEG() e FP_OFF(), definite in DOS.H, che ricavano, rispettivamente, segmento ed offset da puntatori di tipo far (pag.
Se userpath punta alla stringa resolvepath() può essere utilizzata in luogo di getrealdir()
Il servizio 60h dell'int 21h non è ufficialmente documentato : ad esempio, non sembra essere implementato nel DR‑DOS 5.0, rilasciato alcuni mesi dopo lo sviluppo delle due funzioni descritte. Come accade spesso quando si sfruttano caratteristiche non ufficiali del sistema operativo, è stato indispensabile correre ai ripari, scrivendo una funzione in grado di emulare il servizio 60h.
BARNINGA_Z! - 1991
PATHNAME.C - pathname()
pathname() Risolve un pathname in pathname completo
SINTASSI int cdecl pathname(char *path,char *src,char *badchrs);
PARAMETRI path puntatore ad un'area di memoria di almeno
MAXPATH (80) caratteri (MAXPATH è definita
in fileutil.h) in cui è costrutio il
pathname completo. La funzione non controlla
la lunghezza del buffer; assume
semplicemente che esso sia sufficiente a
contenere tutto il pathname.
src puntatore al pathname sorgente. Se la
stringa è vuota, in pcompl viene posto il
pathname della directory corrente del drive
di default, seguita da una backslash.
badchrs puntatore ad una stringa contenente i
caratteri che devono essere considerati
illeciti in un pathname oltre ai caratteri
da 0x00 a 0x1F. In fileutil.h è definita la
stringa BADCHARS ';,:|><'. I due punti (:)
sono comunque ammessi nell'indicatore del
drive.
SCOPO Trasforma un pathname (src) in pathname completo di drive,
percorso e nome di file, considerando gli attuali defaults
di sistema.
RESTITUISCE 0 Operazione completata con successo.
EOF In caso di errore. Le variabili globali errno e
doserrno contengono il codice di errore ENOPATH
(path non trovato); errno e doserrno contengono
il codice dell'errore.
NOTE Il path sorgente può contenere '*' e '?'. Gli '*' sono
trasformati nell'opportuno numero di '?'. Le slashes (/)
eventualmente presenti sono convertite in backslashes ().
Il path sorgente può anche non esistere, e può fare
riferimento ad un drive inesistente (nel qual caso il path
fornito è assunto quale entry della root). La presenza di
un carattere illecito nel pathname, o di due o più punti
(.) anche non consecutivi, o due o più backslashes o
slashes consecutive determinano errore. Tutti i caratteri
che seguono un '*' e precedono il '.' o la fine del nome
(se il '.' è già stato incontrato) sono ignorati. Un nome
di directory (o di file) che superi gli 8 caratteri viene
troncato ad 8. L'estensione che superi i 3 caratteri è
troncata a 3. La funzione interpreta '.' e '..'; tuttavia
esse devono (ovviamente) trovarsi all'inizio del path
sorgente o immediatamente dopo i due punti (:)
dell'indicativo del drive, onde evitare una condizione di
errore. Il pathname costruito in pcompl non termina con
backslash, a meno che si tratti di root o il path in input
(src) sia una stringa vuota.
COMPILABILE CON TURBO C++ 1.0
tcc -O -d -rd -c -mx PATHNAME.C
dove -mx puo' essere -mt -ms -mc -mm -ml -mh
#pragma warn -pia
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <dir.h>
#define NAMELEN (MAXFILE-1) /* lunghezza nomi file */
#define EXTLEN (MAXEXT-2) /* lunghezza estensione */
#define CURRENT '.'
#define CURDIR '.'
#define PARENT '..'
#define PARDIR '..'
#define PARDIR2 '..'
#define ROOTSYM ':'
#define SLASH '/'
#define BSLASH ''
#define COLON ':'
#define POINT '.'
#define ASTERISK '*'
#define QMARK '?'
#define D_FIRST 'A'
#define islwctl(c) ((c >= 0 && c < 0x20) ? 1 : 0) /* macro per chr ctl */
#define isslash(c) ((c == SLASH || c == BSLASH) ? 1 : 0) /* separatore? */
int pascal __IOerror(int dosErr); /* funzione C per condizione d'errore */
int pathname(char *pcompl,char *src,char *badchrs)
flag;
for(cnt = 0; src[cnt]; cnt++)
temp[cnt] = (src[cnt] == SLASH) ? BSLASH : src[cnt]; /* / --> */
temp[cnt] = NULL;
if(temp[--cnt] == BSLASH) /* il path in input non puo' */
if(cnt > 0 && strstr(temp,ROOTSYM) != temp+cnt-1) /* finire in a */
return(__IOerror(ENOPATH)); /* meno che sia root */
if(cnt > 0 && temp[1] == COLON)
else
pcompl[1] = COLON;
pcompl[2] = BSLASH;
px = MAXDRIVE; /* costruito d: */
flag.c = 0;
if(temp[sx] == BSLASH)
else
else
else
}
while(ptr = strstr(temp+sx,PARDIR2))
}
return(__IOerror(ENOPATH)); /* '..' in posiz. errata */
}
}
}
if(!getcurdir((*pcompl)-D_FIRST+1,pcompl+px)) /* dir di default */
if((px = strlen(pcompl)) > MAXDRIVE)
if(cnt)
}
for(flag.w = 0, flag.p = 0, cnt = NAMELEN; temp[sx]; )
else
if(flag.b || flag.p || flag.w)
return(__IOerror(ENOPATH));
flag.b = 1;
cnt = NAMELEN;
break;
case POINT:
if(flag.b || flag.p)
return(__IOerror(ENOPATH));
flag.p = 1;
cnt = EXTLEN;
break;
default:
if(strchr(badchrs,pcompl[px]) || islwctl(pcompl[px]))
return(__IOerror(ENOPATH));
flag.b = 0;
if(!cnt)
if(pcompl[px] == QMARK)
flag.w = 1;
else
if(pcompl[px] == ASTERISK)
continue;
}
--cnt;
}
++sx;
++px;
}
pcompl[px] = NULL;
cnt = strlen(pcompl)-1;
if((pcompl[cnt] == BSLASH) && strlen(pcompl) != MAXDRIVE && *temp)
--px; /* elimina finale a meno che sola o temp vuota */
else
if(strlen(pcompl) == MAXDRIVE-1) /* aggiunge se path e' */
pcompl[px++] = BSLASH; /* d: e la finale e' stata tolta */
return(pcompl[px] = NULL); /* da eliminzaione dirs per '..' */
La pathname() non è in grado di riconoscere i pathname originali sottostanti ridefinizioni effettuate da JOIN e SUBST
Si noti l'uso della funzione (non documentata) di libreria __IOerror(), mediante la quale sono valorizzate le variabili globali errno e doserrno, al fine di rendere la gestione degli errori coerente con lo standard di libreria (per i dettagli su __IOerror() vedere pag.
Appunti su: |
|